﻿//Copyright (c) 2010 Christopher E. S. King (http://chriskingconsulting.com)
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 
// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do 
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Linq.Mapping;
using System.Data.Linq;
using System.Net;
using System.Xml;

using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

using King.Infoset;
using King.Infoset.Schema;
using King.Infoset.Reflection;
using King.Infoset.Entity;
using King.Extensions;
using King.Diagnostics;
using King.Database.Microsoft;
using King.Linq;

using King.Database;
using King.Open.Format;
using King.Open.Format.CSharp;

using db = King.Database.KingDataContext.Tables;

using SR.Utility.TimeZone;
using CommonResources;
using King.Report;

using System.Xml.Serialization;

using King.Open.CSharp;
using King.Open.Linq;
using King.Open.Reflection;
using King.Open.Format.Html;
using King.Open.Format.Html.Pre;
using King.Open.Format.VisualStudio;
using King.Open.Format.IO;
using King.Open.Format.Bat;
using Microsoft.Web.Administration;
//using System.DirectoryServices;
using King.Open.Format.Iis;
using System.Security.Cryptography.X509Certificates;

namespace King.SvcUtil {

    public class Base {
        public virtual void Foo() { }
    }
    public class Derived : Base {
        public override void Foo() { }
    }
    public class SuperDerived : Derived {
        public override void Foo() { }
    }

    public class Program {

        #region Static Internal Data Members
        internal static int BigEnumLimit = 50;
        #endregion

        #region Static Public Members
        public static void Usage() {
            Console.WriteLine("usage: svcutil.exe /client [input.xml] [client.cs]");
            Console.WriteLine("usage: svcutil.exe /schema [adify.service.dll] [services.xsd]");
            Console.WriteLine("usage: svcutil.exe /progress [adify.service.dll] [types.csv] [operation.csv]");
            Console.WriteLine("usage: svcutil.exe /server [server.cs]");
            throw new Exception("Invalid arguments");
        }
        public static void Main(string[] args) {

            if (args == null || args.Length == 0)
                Usage();

            string @switch = args[0];

            if (Regex.IsMatch(@switch, "/client") && args.Length == 4) {
                Client.Generate(args[1], args[2], args[3]);

            } else if (Regex.IsMatch(@switch, "/docclient") && args.Length == 4) {
                DocClient.Generate(args[1], args[2], args[3]);

                //} else if (Regex.IsMatch(@switch, "/deployment") && args.Length == 2) {
                //    GenerateDeployment.Generate(args[1]);

            } else if (Regex.IsMatch(@switch, "/buildDepends") && args.Length == 2) {
                BuildDepends.Generate(args[1]);

            } else if (Regex.IsMatch(@switch, "/templates") && args.Length == 3) {
                Templates.GenerateTemplates(args[1], args[2]);

            } else if (Regex.IsMatch(@switch, "/report") && args.Length == 2) {
                ReportGenerator.Generate(args[1]);

            } else if (@switch == "/constants" && args.Length == 2) {
                var constantsPath = args[1];

                var code = Constants.Generate();
                using (var file = new StreamWriter(constantsPath, false))
                    file.Write(TObject.ToString(code));

            } else if (@switch == "/assemblyToHtml" && args.Length == 4) {
                var dllPath = args[1];
                var docPath = args[2];
                var htmlPath = args[3];

                AssemblyToHtml.Generate(dllPath, docPath, htmlPath);

            } else if (@switch == "/doc" && args.Length == 4) {
                var dllPath = args[1];
                var docPath = args[2];
                var htmlPath = args[3];

                var path = Path.Combine(Environment.CurrentDirectory, dllPath);
                var dir = Path.GetDirectoryName(path);
                var dll = Assembly.LoadFile(path);

                if (AppDomain.CurrentDomain.FriendlyName.ToLower() == "adify.svcutil.exe") {
                    if (Directory.Exists(htmlPath))
                        Directory.Delete(htmlPath, true);
                    Directory.CreateDirectory(htmlPath);

                    AppDomain.CreateDomain("Flatten", null, new AppDomainSetup() {
                        AppDomainInitializer = Main,
                        AppDomainInitializerArguments = args
                    });
                    AppDomain.CreateDomain("Structured", null, new AppDomainSetup() {
                        AppDomainInitializer = Main,
                        AppDomainInitializerArguments = args
                    });
                } else {
                    //using (new Timer(AppDomain.CurrentDomain.FriendlyName)) {
                    //    Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);

                    //    bool flatten = AppDomain.CurrentDomain.FriendlyName == "Flatten";
                    //    InitializeAppDomain(dir);

                    //    using (new Timer("Load Documentation"))
                    //        DocumentationLoader.Load(docPath);

                    //    using (var huh = new Timer("Load King Type System")) {
                    //        XsLoader.Options = new XsLoaderOptions() {
                    //            Flatten = flatten
                    //        };
                    //    }

                    //    Doc.GenerateHtml(htmlPath);
                    //}
                }

            } else if (@switch == "/schema" && args.Length == 4) {
                var dllPath = args[1];
                var docPath = args[2];
                var xmlPath = args[3];

                var path = Path.Combine(Environment.CurrentDirectory, dllPath);
                var dir = Path.GetDirectoryName(path);
                var dll = Assembly.LoadFile(path);

                //InitializeAppDomain(dir);
                //DocumentationLoader.Load(docPath);
                //var xml = Schema.Generate();
                //using (var file = new StreamWriter(xmlPath, false))
                //    file.WriteLine(xml);

            } else if (@switch == "/queryable" && args.Length == 2) {
                var csPath = args[1];

                var code = QueryableGen.Generate();
                using (var file = new StreamWriter(csPath, false))
                    file.WriteLine(code);

            } else if (@switch == "/microsoftTables" && args.Length == 3) {
                MicrosoftTables.Generate(args[1], args[2]);

            } else if (@switch == "/tables" && args.Length == 3) {
                KingTables.Generate(args[1], args[2]);

            } else if (@switch == "/dbmetadata" && args.Length == 3) {
                DatabaseMetadata.Generate(args[1], args[2]);

            } else {
                Usage();
            }
        }
        public static IEnumerable<XsContract> GetSubClasses(XsContract contract) {
            InitializeRelationships();
            return GetRelationship(s_subClasses, contract);
        }
        public static IEnumerable<XsContract> GetSignatureTypeIn(XsContract contract) {
            InitializeRelationships();
            return GetRelationship(s_signatureTypeIn, contract);
        }
        public static IEnumerable<XsContract> GetContractMemberIn(XsContract contract) {
            InitializeRelationships();
            return GetRelationship(s_memberIn, contract);
        }
        public static IEnumerable<XsContract> GetAppliedTo(XsContract annotation) {
            InitializeRelationships();
            return GetRelationship(s_appliedTo, annotation);
        }
        #endregion

        #region Static Private Members
        private static IEnumerable<XsContract> GetRelationship(
            Dictionary<object, IEnumerable<XsContract>> relationship,
            object key) {

            IEnumerable<XsContract> result;
            if (!relationship.TryGetValue(key, out result))
                return Enumerable.Empty<XsContract>();
            return result;
        }
        private static void InitializeRelationships() {
            if (s_signatureTypeIn == null) {
                var uses =
                   (from o in XsLoader.Contracts()
                    let operations = o.Operations()
                    let parameters = operations.SelectMany(m => m.Parameters().Union(m.ReturnParameter)).Where(m => m != null)
                    let operationTypes = parameters.Select(p => p.Contract)
                    let contracts = operationTypes.SelectMany(m => m.Constraints().Union(m)).ExceptFor(o)
                    select new { Key = o, Value = contracts })
                    .ToDictionary(o => o.Key, o => new HashSet<XsContract>(o.Value));

                s_signatureTypeIn =
                   (from o in XsLoader.Contracts()
                    from p in uses where p.Value.Contains(o)
                    group p.Key by o)
                    .ToDictionary(o => (object)o.Key, o => (IEnumerable<XsContract>)o.ToList());
            }

            if (s_subClasses == null) {
                s_subClasses =
                   (from o in XsLoader.Contracts()
                    from s in XsLoader.Contracts() where s.IsDerivationOf(o)
                    group s by o)
                    .ToDictionary(o => (object)o.Key, o => (IEnumerable<XsContract>)o.ToList());
            }

            if (s_memberIn == null) {
                var uses =
                   (from o in XsLoader.Contracts()
                    let members = o.DeclaredMembers()
                    let memberTypes = members.Select(m => m.Contract)
                    let contracts = memberTypes.SelectMany(m => m.Constraints().Union(m)).ExceptFor(o)
                    select new { Key = o, Value = contracts })
                    .ToDictionary(o => o.Key, o => new HashSet<XsContract>(o.Value));

                s_memberIn =
                   (from o in XsLoader.Contracts()
                    from p in uses where p.Value.Contains(o)
                    group p.Key by o)
                    .ToDictionary(o => (object)o.Key, o => (IEnumerable<XsContract>)o.ToList());
            }

            if (s_appliedTo == null) {
                //s_appliedTo =
                //   (from o in XsLoader.Attributes()
                //    from p in XsLoader.Contracts()
                //    let annotations = p.AttributeData().Union(
                //        p.Members().Cast<XsInfo>()
                //            .Union(p.Operations().Cast<XsInfo>())
                //            .Union(p.Members().Cast<XsInfo>())
                //            .Union(p.Enums().Cast<XsInfo>())
                //            .Union(p.Constants().Cast<XsInfo>())
                //            .Union(p.Masks().Cast<XsInfo>())
                //            .SelectMany(x => x.AttributeData()))
                //    where annotations.Any(x => x.Attribute == o)
                //    select new { Annotation = o, Contract = p } into o
                //    group o by o.Annotation)
                //    .ToDictionary(o => (object)o.Key, o => o.Select(x => x.Contract));
            }
        }
        internal static void InitializeAppDomain(string dir) {
            AppDomain.CurrentDomain.AssemblyResolve +=
                delegate(object sender, ResolveEventArgs assembly) {
                    var assemblyName = assembly.Name;
                    if (assemblyName.Contains(','))
                        assemblyName = assemblyName.Substring(0, assembly.Name.IndexOf(','));
                    var dllName = assemblyName + ".dll";
                    return Assembly.LoadFile(Path.Combine(dir, dllName));
                };
        }
        #endregion

        #region Static Private Data Members
        private static Dictionary<object, IEnumerable<XsContract>> s_memberIn;
        private static Dictionary<object, IEnumerable<XsContract>> s_signatureTypeIn;
        private static Dictionary<object, IEnumerable<XsContract>> s_subClasses;
        private static Dictionary<object, IEnumerable<XsContract>> s_appliedTo;
        #endregion
    }

    public class CommandAttribute : Attribute { }

    public class KingEnv {
        public static readonly string ADIFY_ROOT = "ADIFY_ROOT";
        public static readonly string ADIFY_DEPLOYMENT = "ADIFY_DEPLOYMENT";
        public static readonly string ADIFY_DEPLOYMENT_ENVIRONMENT = "ADIFY_DEPLOYMENT_ENVIRONMENT";

        public static void SetEnvironment(string root) {
            Environment.SetEnvironmentVariable(KingEnv.ADIFY_ROOT, root);
            Environment.SetEnvironmentVariable(KingEnv.ADIFY_DEPLOYMENT, root + @"deployment\");
            Environment.SetEnvironmentVariable(KingEnv.ADIFY_DEPLOYMENT_ENVIRONMENT, root + @"deployment\env\");
        }
    }

    // /assemblyToHtml King\King.Client\bin\Debug\King.Client.dll King\King.Client\bin\Debug\King.Client.xml Web\King.Service\Documentation\
    [Command]
    internal static class AssemblyToHtml {

        #region Definitions
        internal class HtmlUrl : TObjects {

            #region Private Data Members
            private Uri m_rootUrl;
            private Uri m_assemblyUrl;
            private Uri m_pageUrl;
            #endregion

            #region Constructor
            internal HtmlUrl(Uri rootUrl, Uri assemblyUrl, Uri pageUrl) {
                m_rootUrl = rootUrl;
                m_assemblyUrl = assemblyUrl;
                m_pageUrl = pageUrl;
            }
            #endregion

            #region Public Members
            internal Uri RootUrl {
                get { return m_rootUrl; }
            }
            internal Uri AssemblyUrl {
                get { return m_assemblyUrl; }
            }
            internal Uri PageUrl {
                get { return m_pageUrl; }
            }
            #endregion
        }
        internal class HtmlPrePage : TObjects {

            #region TObject Overrides
            protected override IEnumerable<object> GetContent(TContext context) {
                return new Transforms() {
                    new TIndentValue(HtmlIndent.DefaultIndent) {
                        new HtmlHtml() {
                            Head = new HtmlHead() {
                                Title = Title,
                                Stylesheet = "/documentation/default.css",
                            },

                            Body = new HtmlBody() {
                                new HtmlPre(CSIndent.DefaultIndent) {
                                    Body
                                }
                            }
                        }
                    }
                };
            }
            #endregion

            #region Public Members
            public object Title { get; set; }
            public object Body { get; set; }
            #endregion
        }
        public class Transformed : TObjects {

            #region Private Data Members
            private object m_target;
            #endregion

            #region Constructor
            public Transformed(object target) {
                m_target = target;
            }
            #endregion

            #region Public Members
            public object Target {
                get { return m_target; }
            }
            #endregion
        }
        public class Transforms : TObjects {

            #region Private Members
            private Uri GetUrl(TContext context, string ns) {
                var htmlUrl = context.GetValue<HtmlUrl>();
                var targetUrl = new Uri(htmlUrl.AssemblyUrl, ns + "/default.html");
                var relUrl = htmlUrl.PageUrl.MakeRelativeUri(targetUrl);
                return relUrl;
            }
            private Uri GetUrl(TContext context, Type type) {
                var htmlUrl = context.GetValue<HtmlUrl>();
                var targetUrl = AssemblyToHtml.GetTypeUrl(htmlUrl.RootUrl, type);
                var relUrl = htmlUrl.PageUrl.MakeRelativeUri(targetUrl);
                return relUrl;
            }
            private object TransformNamespace(TContext context, CSNamespaceRef ns) {

                return new HtmlAnchor() {
                    Elements = ns,
                    Class = "basic",
                    HRef = GetUrl(context, ns.Namespace).ToString()
                };
            }
            private object TransformTypeRef(TContext context, CSTypeRef typeRef) {
                var type = typeRef.Type;

                return new HtmlAnchor() {
                    Elements = typeRef,
                    Class = type.IsEnum ? "enum" : "complex",
                    HRef = GetUrl(context, typeRef.Type).ToString(),
                };
            }
            private object TransformHelper(TContext context, object value) {

                if (value is CSDocComment)
                    return new HtmlStyleSpan(StyleColor.Gray) { value };

                if (value is CSXText)
                    return new HtmlStyleSpan(StyleColor.Green) { value };

                if (value is CSXElementName)
                    return new HtmlStyleSpan(StyleColor.Gray) { value };

                if (value is CSXAttributeName)
                    return new HtmlStyleSpan(StyleColor.Gray) { value };

                if (value is CSString)
                    return new HtmlStyleSpan(StyleColor.Maroon) { value };

                if (value is CSKeyWord)
                    return new HtmlStyleSpan(StyleColor.Blue) { value };

                if (value is CSTypeName)
                    return new HtmlStyleSpan(StyleColor.Teal) { value };

                if (value is CSTypeRef)
                    return TransformTypeRef(context, (CSTypeRef)value);

                if (value is CSNamespaceRef)
                    return TransformNamespace(context, (CSNamespaceRef)value);

                if (value is CSPreProcessorDirective)
                    return new HtmlStyleSpan(StyleColor.Purple) { value };

                if (value is TXFormat) {
                    var escapeContext = context.GetValue<TXObject>().EscapeContext;
                    if (escapeContext == CSXElement.EscapeContext)
                        return new HtmlStyleSpan(StyleColor.Gray) { value };
                }

                return value;
            }
            private object TransformMarkup(TContext context, object value) {
                var transformed = context.GetValue<Transformed>();
                if (transformed != null && transformed.Target == value)
                    return value;

                var transform = TransformHelper(context, value);
                if (transform == value)
                    return value;

                return new Transformed(value) { transform };
            }
            #endregion

            #region TObject Overrides
            protected override object Transform(TContext context, object value) {
                return TransformMarkup(context, value);
            }
            protected override object Substitute(TContext context, object value) {
                if (value is Documentation)
                    return ((Documentation)value).Summary;
                return value;
            }
            #endregion
        }
        #endregion

        #region Static Internal Members
        internal static void Generate(string assemblyPath, string documentation, string targetPath) {
            var applicationBase = Path.GetDirectoryName(targetPath);

            var appDomain = AppDomain.CreateDomain("AssemblyToHtml", null,
                new AppDomainSetup() {
                    AppDomainInitializer = AppDomainMain,
                    AppDomainInitializerArguments = new[] { assemblyPath, documentation, targetPath },
                }
            );
        }
        internal static void AppDomainMain(string[] arguments) {
            var assemblyPath = arguments[0];
            var documentation = arguments[1];
            var relTargetDir = arguments[2];

            var assemblyDir = Path.GetDirectoryName(assemblyPath);
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += AssemblyResolve(assemblyDir);

            var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
            DocumentationLoader.Load(documentation);

            GenerateAssembly(relTargetDir, assembly);
        }
        private static ResolveEventHandler AssemblyResolve(string directory) {
            return delegate(object sender, ResolveEventArgs assembly) {
                var assemblyName = assembly.Name;
                if (assemblyName.Contains(','))
                    assemblyName = assemblyName.Substring(0, assembly.Name.IndexOf(','));
                var dllName = assemblyName + ".dll";
                var path = Path.Combine(directory, dllName);

                if (File.Exists(path))
                    return Assembly.ReflectionOnlyLoadFrom(path);

                return Assembly.ReflectionOnlyLoad(assembly.Name);
            };
        }
        #endregion

        #region Private Static Members (Html, GetUrl)
        private static void GenerateAssembly(string relDir, Assembly assembly) {

            // get absolute url for the type
            var baseDir = Path.Combine(Environment.CurrentDirectory, relDir);
            var rootUrl = new Uri(Path.Combine(baseDir, "assembly") + "/");
            var assemblyUri = GetUrl(rootUrl, assembly);

            var types =
                from o in assembly.GetTypes()
                where o.IsVisible
                where o.IsClass || o.IsEnum //|| o.IsStruct() || o.IsInterface
                select o;

            var typePages =
                from o in types
                let typeUrl = GetTypeUrl(rootUrl, o)
                select new HtmlUrl(rootUrl, assemblyUri, typeUrl) {
                    new HtmlPrePage() {
                        Title = o.FullName,
                        Body = GenerateType(o),
                    }            
                };

            var namespacePages =
                from o in types
                group o by o.Namespace into o
                let nsUrl = GetNamespaceUrl(rootUrl, assembly, o.Key)
                select new HtmlUrl(rootUrl, assemblyUri, nsUrl) {
                    new HtmlPrePage() {
                        Title = o.Key,
                        Body = GenerateNamespace(assembly, o.Key)
                    }
                };

            var pages = namespacePages.Concat(typePages);

            foreach (var page in pages) {
                Console.WriteLine(page.RootUrl.MakeRelativeUri(page.PageUrl));
                var path = page.PageUrl.LocalPath;
                var dir = Path.GetDirectoryName(path);
                Directory.CreateDirectory(dir);
                using (var file = new StreamWriter(path))
                    file.WriteLine(TObject.ToString(page));
            }
        }
        private static Uri GetUrl(Uri baseUri, Assembly assembly) {
            return new Uri(baseUri, assembly.GetName().Name + "/");
        }
        private static Uri GetNamespaceUrl(Uri baseUri, Assembly assembly, string ns) {
            return new Uri(GetUrl(baseUri, assembly) + ns + "/default.html");
        }
        private static Uri GetTypeUrl(Uri rootUrl, Type type) {
            var namespaceUrl = GetNamespaceUrl(rootUrl, type.Assembly, type.Namespace);
            var pageUrl = new Uri(namespaceUrl, type.ToLinkList(o => o.DeclaringType)
                .Reverse().Select(o => o.Name).StringJoin("+") + ".html");
            return pageUrl;
        }
        #endregion

        #region Private Static Members (CSharp)
        private static object OrderMember(MemberInfo info) {
            return info.Name;
        }
        private static object GeneratePropertyOrField(MemberInfo info) {
            var documentation = info.GetDocumentation();

            return new CSProperty() {
                Documentation = documentation,
                Visibility = CSVisibility.Public,
                Name = info.Name,
                Type = info.GetPropertyOrFieldType()
            };
        }
        private static object GenerateMethod(MethodInfo info) {
            return null;
        }
        private static object GenerateConstructor(ConstructorInfo info) {
            return null;
        }

        private static object GenerateClassStructOrInterfaceMembers(Type type) {

            var code = new TDoubleLine() {

                new CSRegion("Static Members") {
                    from o in type.GetStaticPublic<MemberInfo>(MemberTypes.Property | MemberTypes.Field)
                    orderby OrderMember(o)
                    select GeneratePropertyOrField(o)
                },

                new CSRegion("Static Methods") {
                    from o in type.GetStaticPublic<MethodInfo>()
                    orderby OrderMember(o)
                    select GenerateMethod(o)
                },

                new CSRegion("Constructors") {
                    from o in type.GetInstanceDeclaredOnlyPublic<ConstructorInfo>()
                    orderby OrderMember(o)
                    select GenerateConstructor(o)
                },

                new CSRegion("Members") {
                    new TDoubleLineJoin() {
                        from o in type.GetInstanceDeclaredOnlyPublic<MemberInfo>(MemberTypes.Property | MemberTypes.Field)
                        orderby OrderMember(o)
                        select GeneratePropertyOrField(o)
                    }
                },

                new CSRegion("Methods") {
                    from o in type.GetInstanceDeclaredOnlyPublic<MethodInfo>()
                    orderby OrderMember(o)
                    select GenerateMethod(o)
                },
            };

            return code;
        }
        private static object GenerateEnumMembers(Type type) {

            var enumInfo = EnumInfo.GetEnumInfo(type);
            var enumValues = enumInfo.Values().ToArray();

            var values =
                from o in enumInfo.Values()
                select new {
                    Code = new CSEnumField() {
                        Attributes = GenerateAttributes(o.FieldInfo),
                        Documentation = o.FieldInfo.GetDocumentation(),
                        Name = o.Name,
                        Initializer = CSEnumField.SubstituteEnumValue(o),
                    },
                    MemberInfo = (EnumMemberInfo)o,
                    OrderBy = (long)(
                        o.Mask != null ? o.Mask.LongValue :
                        o.IsFlags ? o.LongValue : -1)
                };

            var mostBitsFirst =
               (from o in enumInfo.Members().Distinct(o => o.LongValue.GetBits())
                let value = o.LongValue
                orderby value == -1, value.GetBits().Count() descending
                select value).ToArray();

            var masks =
                from o in enumInfo.Masks()
                select new {
                    Code = new CSEnumField() {
                        Attributes = GenerateAttributes(o.FieldInfo),
                        Documentation = o.FieldInfo.GetDocumentation(),
                        Name = o.Name,
                        Initializer = CSEnumField.SubstituteEnumMask(o),
                    },
                    MemberInfo = (EnumMemberInfo)o,
                    OrderBy = (long)o.LongValue,
                };

            var groups =
                from o in values.Union(masks)
                group o by mostBitsFirst.FirstOr<long>(x => o.OrderBy.IsSubsetValueOf(x), o.OrderBy)
                    into o
                    orderby (long)o.Key select o;

            var members =
                from o in groups
                select new TSingleLineJoin() {
                    from x in o 
                    orderby x.MemberInfo is MaskValue descending, x.MemberInfo.LongValue
                    select x.Code
                };

            var simpleEnumWithAttributes = !enumInfo.IsFlags && enumInfo.Members().Any(o => o.GetCustomAttributeData().Any());
            var groupedBody = simpleEnumWithAttributes || (groups.MoreThanOne() && groups.Any(o => o.MoreThanOne())) ?
                (object)new TDoubleLine() { members } : members;

            return new CSPadding(enumInfo.Values().Max(o => o.Name.Length)) { groupedBody };
        }
        private static object GenerateAttributes(ICustomAttributeProvider provider) {
            return GenerateAttributes(provider, CSAttributeGroupTarget.None);
        }
        private static object GenerateAttributes(ICustomAttributeProvider provider, CSAttributeGroupTarget target) {

            var result =
                from attributeGroup in
                    from data in provider.GetAttributeData()
                    orderby AttributeInfo.OrderByKey(data.AttributeInfo)
                    group data by AttributeInfo.GroupByKey(data.AttributeInfo)
                select new CSAttributeGroup(target) {
                    from data in attributeGroup
                    select new CSAttribute(data.Type) {
                        from argument in data.Arguments
                        let value = argument.ReflectionOnlyValue
                        where value != null
                        orderby AttributeParameter.OrderByKey(argument.Parameter)
                        let csValue = new CSAttributeValue(value)
                        select argument.IsConstructorParameter ? (object)csValue : 
                            new CSNamedArgument(argument.Name, csValue),
                    }
                };

            return result.ToArray();
        }

        private static object GenerateClass(Type type) {

            var baseType = type.BaseType;
            if (baseType == typeof(object))
                baseType = null;

            return new CSClass() {
                Attributes = GenerateAttributes(type),
                Documentation = type.GetDocumentation(),
                IsStatic = type.IsStatic(),
                Visibility = CSVisibility.Public,
                Name = type,
                BaseType = baseType,
                Interfaces = type.GetInterfaces(),
                Members = GenerateClassStructOrInterfaceMembers(type),
            };
        }
        private static object GenerateStruct(Type type) {
            return new CSStruct() {
                Attributes = GenerateAttributes(type),
                Documentation = type.GetDocumentation(),
                Visibility = CSVisibility.Public,
                Name = type,
                Members = GenerateClassStructOrInterfaceMembers(type),
            };
        }
        private static object GenerateInterface(Type type) {
            return new CSInterface() {
                Attributes = GenerateAttributes(type),
                Documentation = type.GetDocumentation(),
                Visibility = CSVisibility.Public,
                Name = type,
                Interfaces = type.GetInterfaces(),
                Members = GenerateClassStructOrInterfaceMembers(type),
            };
        }
        private static object GenerateEnum(Type type) {

            var baseType = Enum.GetUnderlyingType(type);
            if (baseType == typeof(int))
                baseType = null;

            return new CSEnum() {
                Attributes = GenerateAttributes(type),
                Documentation = type.GetDocumentation(),
                Visibility = CSVisibility.Public,
                Name = type,
                BaseType = baseType,
                Members = GenerateEnumMembers(type),
            };
        }

        private static object GenerateType(Type type) {

            object code = null;

            if (type.IsEnum)
                code = GenerateEnum(type);
            else if (type.IsInterface)
                code = GenerateInterface(type);
            else if (type.IsClass)
                code = GenerateClass(type);
            else if (type.IsStruct())
                code = GenerateStruct(type);

            return new CSNamespace(type.Namespace) {
                Environment.NewLine,
                code
            };
        }
        private static object GenerateNamespace(Assembly assembly, string ns) {
            var types =
                from o in assembly.GetTypes()
                where o.IsVisible
                orderby o.Name
                select o;

            return new TDoubleLineJoin() {
                new TSingleLineJoin() {
                    "Classes",
                    from o in types
                    where o.IsClass
                    select new CSTypeBuilder(o)
                },

                new TSingleLineJoin() {
                    "Enums",
                    from o in types
                    where o.IsSimpleEnum()
                    select new CSTypeBuilder(o)
                },

                new TSingleLineJoin() {
                    "Flags",
                    from o in types
                    where o.IsFlagsEnum()
                    select new CSTypeBuilder(o)
                }
            };
        }
        #endregion
    }

    // /doc KingService\bin\King.Service.dll KingService\King.Service.xml KingService\Documentation\
    [Command]
    internal static class Doc {

#if false

        internal enum TypeSystem {
            CSharp,
            Xsd
        }
        internal enum Layout {
            Flattened,
            Structured
        }
        internal sealed class DocUrl : Format {

        #region Static Internal Data Members
            internal static Uri BaseUrl = new Uri("http://service.adify.com/documentation/");
            internal static Uri CssUrl;
            internal static Uri SpecUrl;
            internal static Uri BigEnumsCSharp;
            internal static Uri BigEnumsSchema;
            internal static Uri BasePath;
            internal static Uri DocPath;
            #endregion

        #region Static Internal Members
            internal static void Initialize(string htmlPath) {
                CssUrl = new Uri(BaseUrl, @"default.css");
                SpecUrl = new Uri(BaseUrl, "KingApiUserGuide.pdf");
                BigEnumsCSharp = new Uri(BaseUrl, "BigEnums.cs");
                BigEnumsSchema = new Uri(BaseUrl, "BigEnums.xsd");
                BasePath = new Uri(new Uri(Environment.CurrentDirectory + "\\"), htmlPath);
                DocPath = new Uri(BasePath, "../Doc");
            }
            #endregion

        #region Implicit Operator
            public static bool operator ==(DocUrl lhs, DocUrl rhs) {
                return object.Equals(lhs, rhs);
            }
            public static bool operator !=(DocUrl lhs, DocUrl rhs) {
                return !object.Equals(lhs, rhs);
            }
            public static implicit operator Uri(DocUrl docUrl) {
                return docUrl.m_url;
            }
            #endregion

        #region Private Data Members
            private TypeSystem m_typeSystem;
            private Layout m_layout;
            private string m_name;
            private Uri m_url;
            private bool m_completeEnum;
            #endregion

        #region Constructor
            public DocUrl(DocUrl baseDocUrl, string name)
                : this(
                baseDocUrl.m_typeSystem,
                baseDocUrl.m_layout,
                name) {
            }
            public DocUrl(TypeSystem typeSystem, Layout layout)
                : this(typeSystem, layout, null) {
            }
            public DocUrl(TypeSystem typeSystem, Layout layout, string name)
                : this(typeSystem, layout, false, name) {
            }
            public DocUrl(TypeSystem typeSystem, Layout layout, bool bigEnum, string name) {
                m_typeSystem = typeSystem;
                m_layout = layout;
                m_name = name;
                m_completeEnum = bigEnum;

                var html = (m_name == null ? "default" : m_name) + (m_completeEnum ? ".everything" : null) + ".htm";
                m_url = new Uri(BaseUrl, m_layout + "/" + m_typeSystem + "/" + html);
            }
            #endregion

        #region Format Overrides
            protected override bool IsEmptyImpl() {
                return false;
            }
            protected override void Evaluate() {
                Append(m_url);
            }
            #endregion

        #region Public Members
            public Uri Url { get { return m_url; } }
            public DocUrl CSharp {
                get {
                    return new DocUrl(TypeSystem.CSharp, m_layout, m_completeEnum, m_name);
                }
            }
            public DocUrl Xsd {
                get {
                    return new DocUrl(TypeSystem.Xsd, m_layout, m_completeEnum, m_name);
                }
            }
            public DocUrl CompleteEnum {
                get {
                    return new DocUrl(m_typeSystem, m_layout, true, m_name);
                }
            }
            public DocUrl SampleEnum {
                get {
                    return new DocUrl(m_typeSystem, m_layout, false, m_name);
                }
            }
            public DocUrl Structured {
                get {
                    return new DocUrl(m_typeSystem, Layout.Structured, m_completeEnum, m_name);
                }
            }
            public DocUrl Flattened {
                get {
                    return new DocUrl(m_typeSystem, Layout.Flattened, m_completeEnum, m_name);
                }
            }
            public DocUrl TableOfContent {
                get {
                    return new DocUrl(m_typeSystem, m_layout);
                }
            }
            public DocUrl Index {
                get {
                    return new DocUrl(m_typeSystem, m_layout, "Index");
                }
            }
            public DocUrl AllIn1 {
                get {
                    return new DocUrl(m_typeSystem, m_layout, "AllIn1");
                }
            }
            public DocUrl Stats {
                get {
                    return new DocUrl(m_typeSystem, m_layout, "Stats");
                }
            }
            public Uri Path {
                get {
                    return new Uri(BasePath, BaseUrl.MakeRelativeUri(m_url));
                }
            }

            public Uri MakeRelativeUri(Uri url) {
                return m_url.MakeRelativeUri(url);
            }
            public Uri MakeRelativeUri(DocUrl docUrl) {
                return m_url.MakeRelativeUri(docUrl.m_url);
            }
            public Layout Layout { get { return m_layout; } }
            public TypeSystem TypeSystem { get { return m_typeSystem; } }
            public string Name { get { return m_name; } }
            #endregion

        #region Object Overrides
            public override bool Equals(object obj) {
                var rhs = obj as DocUrl;
                if (rhs == null)
                    return false;

                return Url.Equals(rhs.Url);
            }
            public override int GetHashCode() {
                return Url.GetHashCode();
            }
            #endregion
        }

        #region Definitions
        private sealed class HtmlFile : Format {

        #region Private Data Members
            private List<object> m_content;
            private DocUrl m_docUrl;
            #endregion

        #region Constructor
            internal HtmlFile(DocUrl docUrl) {
                m_content = new List<object>();
                m_docUrl = docUrl;
            }
            #endregion

        #region Format Overrides
            protected override bool IsEmptyImpl() {
                return false;
            }
            protected override void Evaluate() {

                var body = Flatten(Body);

                var result =
                    new NewLineJoin() {
                        new InlineString(@"
                            <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
                                                  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
                            <html xmlns='http://www.w3.org/1999/xhtml' >
                            <head>
                                <title>" + ToFormat(Title) + @"</title>
                                <link href='" + m_docUrl.MakeRelativeUri(DocUrl.CssUrl) + @"' rel='stylesheet' type='text/css'> 
                            </head>
                            <body style='font-family: Consolas'>

                            <pre>"
                        ), 
                        new DoubleNewLineJoin() {
                            new SpaceJoin() {
                                new Anchor("UserGuide", 
                                    m_docUrl.MakeRelativeUri(DocUrl.SpecUrl), "basic"), "|",

                                m_docUrl == m_docUrl.TableOfContent ? "Toc" :
                                new Anchor("Toc", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.TableOfContent), "basic"),

                                m_docUrl == m_docUrl.Index ? "Index" :
                                new Anchor("Index", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.Index), "basic"),

                                m_docUrl == m_docUrl.AllIn1 ? "AllIn1" :
                                new Anchor("AllIn1", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.AllIn1), "basic"),

                                m_docUrl == m_docUrl.Stats ? "Stats" :
                                new Anchor("Stats", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.Stats), "basic"), "|",

                                m_docUrl.Layout == Layout.Structured ? "Structured" :
                                new Anchor("Structured", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.Structured), "basic"),

                                m_docUrl.Layout == Layout.Flattened ? "Flattened" :
                                new Anchor("Flattened", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.Flattened), "basic"), "|",

                                m_docUrl.TypeSystem == TypeSystem.Xsd ? "Xsd" :
                                new Anchor("Xsd", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.Xsd), "basic"),

                                m_docUrl.TypeSystem == TypeSystem.CSharp ? "CSharp" :
                                new Anchor("CSharp", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.CSharp), "basic"), 
                                    
                                !IsDataEnum ? null : "|",

                                !IsDataEnum ? null : m_docUrl == m_docUrl.SampleEnum ? "Sample" :
                                new Anchor("Sample", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.SampleEnum), "basic"),

                                !IsDataEnum ? null : m_docUrl == m_docUrl.CompleteEnum ? "Complete" :
                                new Anchor("Complete", 
                                    m_docUrl.MakeRelativeUri(m_docUrl.CompleteEnum), "basic"),
                            }, 
                            body
                        },
                        ToFormat(UsedBy),
                        new InlineString(@"
                            </pre>
                                  
                            </body>
                            </html>"
                        )
                    }.ToString();

                result = result.Replace("<object>", "&lt;object&gt;");

                Append(result);
            }
            #endregion

        #region Internal Members
            internal object Title { get; set; }
            internal object UsedBy { get; set; }
            internal object Body { get; set; }
            internal bool IsDataEnum { get; set; }
            #endregion
        }
        private sealed class KingCSharpCodeFile : EnumerationFormat {

        #region Private Data Members
            private DocUrl m_docUrl;
            #endregion

        #region Constructor
            internal KingCSharpCodeFile(DocUrl docUrl, params object[] content)
                : base(content) {
                m_docUrl = docUrl;
            }
            #endregion

        #region Protected Format Overrides
            protected override void Evaluate() {

                var regex = @"(?<!\w)(?<type>" + XsLoader.Contracts().Select(o => o.Name).StringJoin("|") + @")(?!\w)";
                regex += @"|(?<gray>(?!(" + regex + @"))((///)|([<]/?[^>]+[>])))";
                regex += @"|(?<other>((?!(" + regex + @")|\r|\n).)*)";

                var ctor = new CSharpCodeFile.Ctor() {
                    //OnFormatToString = Client.ContractToCSharpType,
                    OnTypeToString = delegate(Format type) {

                        //var target = XsLoader.TryGetContract(type);
                        var target = XsLoader.GetContract(default(Type));
                        if (target == null)
                            target = XsLoader.GetContractOrNull(King.Extensions.Extensions.GetTypeByKeyword(type));

                        if (target == null)
                            return new Span(type) { Style = "color:teal" };

                        if (target.IsObject)
                            return new Span(type) { Style = "color:blue" };

                        if (target.IsEnumeration)
                            return new Span(type) { Style = "color:teal" };

                        var targetUrl = new DocUrl(m_docUrl, target.Name);

                        var isPrimitive = target.IsPrimitive;
                        var isPrimitiveDefinition = isPrimitive && type.ToString() == target.Name;
                        var cls = isPrimitive ? "primitive" :
                                    target.IsList ? "enum" :
                                    target.IsGroup ? "group" :
                                    "complex";

                        var result = new Anchor(type) {
                            Class = isPrimitiveDefinition ? "complex" : cls,
                            Title = type + " (" + cls.ToUpperFirst() + ")",
                            Href = m_docUrl.MakeRelativeUri(targetUrl)
                        };
                        return result;
                    },

        #region OnXxxToString
                    OnStringToString = delegate(Format target) {
                        return new Span(target) { Style = "color:maroon" };
                    },
                    OnDocCommentToString = delegate(Format docComment) {
                        return Regex.Replace(docComment, regex, delegate(Match m) {
                            var type = m.Groups["type"].Value;
                            var other = m.Groups["other"].Value;
                            var gray = m.Groups["gray"].Value;

                            string result = null;
                            if (!string.IsNullOrEmpty(type)) {
                                var csharpType = (CSharpType)ToFormat(XsLoader.GetContract(type).MakeCanBeEmpty());
                                csharpType.IsNullable = false;
                                result = csharpType;
                            } else if (!string.IsNullOrEmpty(gray)) {
                                result = new Span(gray) { Style = "color:gray" };
                            } else if (!string.IsNullOrEmpty(other)) {
                                result = new Span(other) { Style = "color:green" };
                            }
                            return result;
                        });
                    },
                    OnCommentToString = delegate(Format comment) {
                        return new Span(comment) { Style = "color:green" };
                    },
                    OnMethodToString = delegate(Format method) {
                        return new Span(method);
                    },
                    OnFieldToString = delegate(Format field) {
                        return new Span(field);
                    },
                    OnPropertyToString = delegate(Format property) {
                        return new Span(property);
                    },
                    OnKeyWordToString = delegate(Format type) {
                        return new Span(type) { Style = "color:blue" };
                    },
                    OnPreprocessorKeyWordToString = delegate(Format type) {
                        return new Span(type) { Style = "color:purple" };
                    },
                    OnBodyToString = delegate(Format type) {
                        return Format.Empty;
                    },
                    #endregion
                };

                var code = new CSharpCodeFile(ctor, Content);
                AppendLine(code);
            }
            #endregion
        }
        private sealed class KingXsdCodeFile : EnumerationFormat {

        #region Private Data Members
            private DocUrl m_docUrl;
            #endregion

        #region Constructor
            internal KingXsdCodeFile(DocUrl docUrl, params object[] content)
                : base(content) {
                m_docUrl = docUrl;
            }
            #endregion

        #region Private Members
            [ThreadStatic]
            private static bool t_isFormatting;
            private Format HtmlFormatting(object html) {
                if (t_isFormatting)
                    return null;
                t_isFormatting = true;
                var result = html.ToString();
                t_isFormatting = false;
                return new XmlRawText(result);
            }
            #endregion

        #region Protected Overrides
            protected override void Evaluate() {

                var commentRegex = @"(?<!\w)(?<type>" + XsLoader.Contracts().Select(o => o.Name).StringJoin("|") + @")(?!\w)";
                commentRegex += @"|(?<other>((?!(" + commentRegex + @")|\r|\n).)*)";

                var xsdCtor = new XsdScope.Ctor() {

        #region XsdScope
                    OnTypeToString = delegate(Format qName) {

                        var regex = Regex.Match(qName, @"^((?<prefix>\w+):)?(?<name>\w+)(?<isArray>\[\])?$");
                        var prefix = regex.Groups["prefix"].Value;
                        var type = regex.Groups["name"].Value;
                        var isArray = regex.Groups["isArray"].Success;

                        var xName =
                          ((from o in GetLocals<XmlPrefix>()
                            where o.Prefix == prefix
                            select o.Namespace)
                            .FirstOrDefault() ?? XsInfoset.XNamespace) + type;

                        object result = null;

                        var target = XsLoader.GetContractOrNull(xName);
                        if (target == null)
                            result = new Span(xName) { Style = "color:teal" };

                        else if (target.IsObject)
                            result = new Span(xName) { Style = "color:teal" };

                        else if (target.IsEnumeration)
                            result = new Span(xName) { Style = "color:teal" };

                        else {
                            var targetUrl = new DocUrl(m_docUrl, target.Name);

                            var isPrimitive = target.IsPrimitive;
                            var isPrimitiveDefinition = isPrimitive && type.ToString() == target.Name;
                            var cls = isPrimitive ? "primitive" :
                                        target.IsList ? "enum" :
                                        target.IsGroup ? "group" :
                                        "complex";

                            result = new Anchor(string.IsNullOrEmpty(prefix) ? xName.LocalName : xName) {
                                Class = isPrimitiveDefinition ? "complex" : cls,
                                Title = type + " (" + cls.ToUpperFirst() + ")",
                                Href = m_docUrl.MakeRelativeUri(targetUrl)
                            };
                        }

                        if (isArray)
                            result = new Concat(result, "[]");

                        return HtmlFormatting(result);
                    }
                    #endregion
                };

                var xmlCtor = new XmlScope.Ctor() {

        #region XmlScope
                    OnFormatToString = Schema.ToFormat,

                    OnXmlToString = delegate(Format xml) {
                        return HtmlFormatting(new Span(xml) { Style = "color:blue" });
                    },
                    OnElementNameToString = delegate(Format name) {
                        return HtmlFormatting(new Span(name) { Style = "color:brown" });
                    },
                    OnAttributeNameToString = delegate(Format name) {
                        return HtmlFormatting(new Span(name) { Style = "color:red" });
                    },
                    OnStringToString = delegate(Format target) {
                        return HtmlFormatting(new Span(target is XmlRawText ? target : new XmlTextFormat(target)) { Style = "color:blue" });
                    },
                    OnCommentToString = delegate(Format target) {
                        return Regex.Replace(target, commentRegex, delegate(Match m) {
                            var type = m.Groups["type"].Value;
                            var other = m.Groups["other"].Value;

                            string result = null;
                            if (!string.IsNullOrEmpty(type)) {
                                result = HtmlFormatting(xsdCtor.OnTypeToString(ToFormat(XsLoader.GetContract(type).MakeCanBeEmpty().Name)));
                            } else if (!string.IsNullOrEmpty(other)) {
                                result = HtmlFormatting(new Span(other) { Style = "color:green" });
                            }
                            return result;
                        });
                    },
                    #endregion
                };

                AppendLine(new XmlScope(xmlCtor) {
                    new XsdScope(xsdCtor) {
                        Content 
                    }
                });
            }
            #endregion
        }
        #endregion

        #region Static Private Data Members
        private static Layout Layout;
        internal static int LexiconCount;
        #endregion

        #region Static Private Members
        private static void Save(Uri path, string content) {
            var localPath = path.LocalPath;
            Directory.CreateDirectory(Path.GetDirectoryName(localPath));
            File.WriteAllText(localPath, content);
        }
        private static void GenerateTableOfContent(TypeSystem typeSystem) {

            var docUrl = new DocUrl(typeSystem, Layout);

            var entity = XsLoader.GetContractOrNull("Entity");
            var code = new ShallowDoubleNewLineJoin() {

        #region Partitions
                    new NewLineJoin("Complex Data Contracts (Entities)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsDerivationOf(entity) && !o.IsDeriveByRestriction
                            where !o.IsAbstract
                            select o
                        }
                    },

                 new NewLineJoin("Complex Data Contracts (Derive By Extension & Abstract)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsAbstract && !o.IsDeriveByRestriction
                            select o
                        }
                    },

                    new NewLineJoin("Complex Data Contracts (Derive By Restriction & Abstract)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsAbstract && o.IsDeriveByRestriction
                            select o
                        }
                    },

                    new NewLineJoin("Complex Data Contracts (Derive By Restriction)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where !o.IsAbstract && o.IsDeriveByRestriction
                            select o
                        }
                    },

                    docUrl.Layout == Layout.Flattened ? null :
                        new NewLineJoin("Complex Data Contracts (Group)") {
                            new Indent() {
                                from o in XsLoader.Contracts()
                                where o.IsGroup
                                select o
                            }
                        },
    
                    new NewLineJoin("Complex Data Contracts (Entities)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsComplex 
                            where !o.IsGroup && 
                                  !o.IsObject &&
                                  !o.IsDerivationOf(entity) &&
                                  o != entity && !o.IsAbstract
                            select o
                        }
                    },
    
                    new NewLineJoin("Simple Data Contracts") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsSimple 
                            where !o.IsDerivationOf(XsLoader.StringContract) && !o.IsPrimitive
                            select o
                        }
                    },
    
                    new NewLineJoin("Simple Data Contracts (Regex)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsSimple 
                            where o.ToLinkList(x => x.BaseContract).First(x => x.IsPrimitive) == XsLoader.StringContract
                            where o != XsLoader.StringContract && !o.IsList
                            select o
                        }
                    },
    
                    new NewLineJoin("Simple Data Contracts (Flags)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsList && o.IsFlags
                            select new CSharpType() {
                                Name = o.Name
                            }
                        }
                    },
    
                    new NewLineJoin("Simple Data Contracts (Enums)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsList && !o.IsFlags
                            select new CSharpType() {
                                Name = o.Name
                            }
                        }
                    },   
    
                    new NewLineJoin("Simple Data Contracts (Constants)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsList
                            select new CSharpType() {
                                Name = o.Name
                            }
                        }
                    },   
    
                    new NewLineJoin("Simple Data Contracts (Primitives)") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where o.IsSimple && o.IsPrimitive
                            where !o.IsObject
                            select o
                        }
                    },
    
                    new NewLineJoin("Annotations") {
                        new Indent() {
                            from o in XsLoader.Contracts()
                            where !o.IsAbstract
                            orderby o.Name
                            select new CSharpType() {
                                Name = o.Name
                            }
                        }
                    },
    
                    new NewLineJoin("Not Yet Implemented") {
                        new Indent() {
                            from d in XsLoader.Contracts()
                            from o in d.Operations()
                            where o.MethodInfo.IsNotImplemented()
                            select new Concat() {
                                new CSharpType() { Name = o.DeclaringContract.Name }, ".", o.Name
                            }
                        }
                    },
    
                    //new NewLineJoin("Unused") {
                    //    new Indent() {
                    //        from o in Loader.Contracts
                    //        where Program.GetContractMemberIn(o).None() &&
                    //              Program.GetSignatureTypeIn(o).None() &&
                    //              Program.GetSubClasses(o).None()
                    //        select new CSharpType() {
                    //            Name = o.Name
                    //        }
                    //    }
                    //},
                    #endregion

                };

            Save(docUrl.Path,
                new HtmlFile(docUrl) {
                    Title = "King Service in {0} ({1})".Substitute(docUrl.TypeSystem, docUrl.Layout),
                    Body = new KingCSharpCodeFile(docUrl, code),
                });
        }
        private static void GenerateUberFiles(XsAssembly assembly) {

            using (new Timer("Uber files")) {

                var docUrl = new DocUrl(TypeSystem.Xsd, Layout).AllIn1;
                //Save(docUrl.Path,
                //    new HtmlFile(docUrl) {
                //        Title = "King Service in {0}".Substitute(docUrl.TypeSystem),
                //        Body = new KingXsdCodeFile(docUrl) { 
                //            Schema.Generate()
                //        }
                //    });

                docUrl = new DocUrl(TypeSystem.CSharp, Layout).AllIn1;
                Save(docUrl.Path,
                    new HtmlFile(docUrl) {
                        Title = "King Service in {0}".Substitute(docUrl.TypeSystem),
                        Body = new KingCSharpCodeFile(docUrl) { 
                            Client.Generate(assembly)
                        }
                    });
            }
        }
        private static void GenerateType(DocUrl docUrl, object body) {
            Save(docUrl.Path,
                new HtmlFile(docUrl) {
                    Title = "{0} in {1} ({2})".Substitute(docUrl.Name, docUrl.TypeSystem, docUrl.Layout),
                    Body = body,
                });
        }
        private static void GenerateXsd(XsContract contract, DocUrl docUrl, bool crossLink) {

            var adifyCtor = new XmlScope.Ctor() {

        #region XmlScope
                OnFormatToString = Schema.ToFormat,
                #endregion
            };

            var body = new object[] { 
                new XsdSchema() {
                    ElementFormDefault = Xs.Qualified,
                    TargetNamespace = XsInfoset.XNamespace,
                    Prefix = Xs.Prefix,
                    Content = new object[] { 
                        new XmlAttributeFormat(XNamespace.Xmlns + "tns", XsInfoset.XNamespace),
                        new XmlAttributeFormat(XNamespace.Xmlns + "md", XsType.XNamespace),
                        new XmlAttributeFormat(XNamespace.Xmlns + "svc", XsType.XNamespace),
                        contract.ToXsd()
                    }
                }
            };

            GenerateType(docUrl, crossLink ?
                (object)new KingXsdCodeFile(docUrl) { body } :
                new XText(new Concat(body).ToString()));
        }
        private static void GenerateCSharp(XsContract contract, DocUrl docUrl) {

            var body = new object[] { 
                contract.ToCSharp()
            };

            GenerateType(docUrl, (object)new KingCSharpCodeFile(docUrl) { body });
        }
        private static void GenerateTypes() {

            foreach (var contract in
                from o in XsLoader.Contracts()
                where !o.IsObject && !o.IsEnumeration && !o.IsXml
                select o) {

                using (new Timer(contract.Name)) {

                    var xsdDocUrl = new DocUrl(TypeSystem.Xsd, Layout, contract.Name);
                    var csharpDocUrl = xsdDocUrl.CSharp;

                    //GenerateXsd(contract, xsdDocUrl, true);
                    GenerateCSharp(contract, csharpDocUrl);
                }
            }
        }
        private class IndexMember {
            internal string Name;
            internal object Target;
            internal XsContract Type;
        }
        private static void GenerateIndex(IEnumerable<IndexMember> members, string name) {

            using (new Timer("Index")) {

                var union =
                    from o in members
                    from s in DecomposeCamelCaseIdentifier(o.Name).Union(o.Name)
                    select new {
                        Incice = s,
                        o.Name,
                        o.Target,
                        o.Type,
                        IsSplit = s != o.Name
                    };

                var index =
                    from o in union
                    group o by o.Incice into o
                    orderby o.Key
                    select new { Value = o.Key, Values = o.ToArray() } into o
                    group o by o.Value[0].ToString().ToUpper() into o
                    orderby o.Key
                    select new { Value = o.Key, Values = o.ToArray() };

                var stripNullable = (Func<XsContract, CSharpType>)delegate(XsContract o) {
                    var csharpType = (CSharpType)Client.ContractToCSharpType(o);
                    csharpType.IsNullable = false;
                    return csharpType;
                };

                LexiconCount = index.SelectMany(o => o.Values).Count();

                var indexHtml = (Func<DocUrl, HtmlFile>)delegate(DocUrl docUrl) {
                    return new HtmlFile(docUrl) {
                        Title = "King Service Index in {0}".Substitute(docUrl.TypeSystem),
                        Body = new KingCSharpCodeFile(docUrl) { 
                            new DoubleNewLineJoin() {
                                from letter in index
                                select new NewLineJoin() {
                                    letter.Value, // A, B, C, ..., Z
                                    new Indent() {
                                        from indice in letter.Values // Above, AboveRateCard, ..., Yes, YesNo
                                        let pivot = indice.Values.Any(o => o.IsSplit)
                                        select new Concat(indice.Value, ": ", 
                                            !pivot ?
                                                (object)new CommaJoin(
                                                    from d in indice.Values.Select(i => i.Type).Distinct()
                                                    orderby d.Name
                                                    select stripNullable(d)
                                                )
                                            : 
                                                new Indent(new NewLine(
                                                    from split in indice.Values.GroupBy(o => o.Name)
                                                    orderby split.Key
                                                    select new Concat(split.Key, ": ",
                                                        new CommaJoin(
                                                            from d in split.Select(i => i.Type).Distinct()
                                                            orderby d.Name
                                                            select stripNullable(d)
                                                        )
                                                    )
                                                ))
                                        )
                                    }
                                }
                            }
                    }
                    };
                };

                var xsd = new DocUrl(TypeSystem.Xsd, Layout, name);
                Save(xsd.Path, indexHtml(xsd));

                var csharp = new DocUrl(TypeSystem.CSharp, Layout, name);
                Save(csharp.Path, indexHtml(csharp));
            }
        }
        private static void GenerateAllIndex() {

            var contracts =
                from o in XsLoader.Contracts()
                where !o.IsObject && !o.IsEnumeration && !o.IsXml && !o.IsPrimitive
                select o;

            var types =
                from o in contracts
                select new IndexMember() {
                    Name = o.Name,
                    Target = (object)o,
                    Type = o
                };

            var fields =
                from o in contracts
                from m in o.DeclaredMembers()
                select new IndexMember() {
                    Name = m.Name,
                    Target = (object)m,
                    Type = o
                };

            var operations =
                from o in contracts
                from m in o.Operations()
                select new IndexMember() {
                    Name = m.Name,
                    Target = (object)m,
                    Type = o
                };

            var enums =
                from o in contracts
                where o.IsList
                from e in o.Enums()
                select new IndexMember() {
                    Name = e.Name,
                    Target = (object)e,
                    Type = o
                };

            GenerateIndex(types.Union(fields).Union(operations).Union(enums), "Index");
        }
        private static void GenerateStats() {

            var contracts = XsLoader.Contracts();
            var members = contracts.SelectMany(o => o.Members());
            var operations = contracts.SelectMany(o => o.Operations());
            var entity = XsLoader.GetContractOrNull("Entity");

            var stats = new[] {
                    new { Name = "Contracts", Value = contracts.Count() },
                    new { Name = "  Complex", Value = contracts.Count(o => o.IsComplex) },
                    new { Name = "    Entity", Value = contracts.Count(o => o.IsDerivationOf(entity)) },
                    new { Name = "  Group", Value = contracts.Count(o => o.IsGroup) },
                    new { Name = "  Simple", Value = contracts.Count(o => o.IsSimple) },
                    new { Name = "    Pattern", Value = contracts.Count(o => o.Regex != null) },
                    new { Name = "    Enum", Value = contracts.Count(o => o.IsList) },
                    new { Name = "      Enum Values", Value = contracts.Where(o => o.IsList).SelectMany(o => o.Enums()).Count() },

                    new { Name = "ContractMembers", Value = members.Count() },

                    new { Name = "Operations", Value = operations.Count() },
                    new { Name = "  Static", Value = operations.Count(o => o.IsStatic) },
                    new { Name = "  Instance", Value = operations.Count(o => !o.IsStatic) },
                    
                    new { Name = "Lexicon", Value = LexiconCount },
                };

            stats =
               (from o in stats
                let maxName = stats.Max(x => x.Name.Length)
                select new {
                    Name = o.Name.PadRight(maxName),
                    Value = o.Value
                }).ToArray();

            var statsHtml = (Func<DocUrl, string>)delegate(DocUrl docUrl) {
                return new HtmlFile(docUrl) {
                    Title = "King Statistics ({0})".Substitute(docUrl.Layout),
                    Body = new NewLineJoin() {
                        from o in stats
                        select new Concat(o.Name, " : ", o.Value)
                    }
                };
            };

            var xsd = new DocUrl(TypeSystem.Xsd, Layout).Stats;
            Save(xsd.Path, statsHtml(xsd));

            var csharp = new DocUrl(TypeSystem.CSharp, Layout).Stats;
            Save(csharp.Path, statsHtml(csharp));
        }
        #endregion

        #region Static Internal Methods
        internal static IEnumerable<string> DecomposeCamelCaseIdentifier(string identifier) {
            if (identifier.ToCharArray().Count(o => char.IsUpper(o)) <= 1)
                yield break;

            var split = string.Empty;
            foreach (var c in identifier.ToCharArray()) {
                if ((char.IsUpper(c) || char.IsDigit(c)) && !string.IsNullOrEmpty(split)) {
                    yield return split;
                    split = string.Empty;
                }

                if (!char.IsDigit(c))
                    split += c;
            }

            if (!string.IsNullOrEmpty(split))
                yield return split;
        }
        internal static void GenerateHtml(string htmlPath) {
            DocUrl.Initialize(htmlPath);
            Layout = XsLoader.Options.Flatten ? Layout.Flattened : Layout.Structured;

            Directory.CreateDirectory(DocUrl.BasePath.LocalPath);
            foreach (var file in Directory.GetFiles(DocUrl.DocPath.LocalPath))
                File.Copy(file, DocUrl.BasePath.LocalPath + Path.GetFileName(file), true);

            Client.IsDocs = true;
            Schema.Docs = true;

            GenerateAllIndex();
            GenerateTableOfContent(TypeSystem.CSharp);
            GenerateTableOfContent(TypeSystem.Xsd);
            GenerateTypes();
            GenerateUberFiles(null);
            GenerateStats();
        }
        #endregion
#endif
    }

    // /client King\King\bin\debug\King.dll King\King\King.xml King\King.Client\Client.Generated.cs
    [Command]
    internal static class Client {

        #region Definitions
        private class XsContractToCSType : TObjects {

            #region Static Private Members
            private static object ContractToCSharp(XsContract contract) {
                object result = contract;

                // ClientType
                if (contract.ClientType != null) {
                    if (contract.ClientContract != null)
                        result = ContractToCSharp(contract.ClientContract);

                    else {
                        var clientType = contract.ClientType;
                        if (clientType.IsValueType && contract.IsOptional)
                            clientType = clientType.MakeNullable();
                        result = clientType;
                    }

                } else if (contract.IsObject) {
                    if (contract.Constraints().None())
                        result = typeof(object);
                    else
                        result = ContractToCSharp(contract.ContstraintsCommonBaseContract);

                } else if (contract.IsUnion) {
                    result = typeof(object);

                } else if (contract.IsEnumeration) {
                    result = new CSTypeBuilder() {
                        Name = typeof(IEnumerable),
                        GenericArguments = ContractToCSharp(contract.ElementContract)
                    };

                } else if (contract.IsEnum) {
                    result = new CSTypeBuilder() {
                        Name = contract.Name,
                        IsNullable = contract.IsOptional,
                    };

                } else if (contract.IsXml) {
                    result = contract.DeserializedType;

                } else if (contract.IsSimple) {
                    var primitiveBaseContract = contract.ToLinkList(o => o.BaseContract).First(o => o.IsPrimitive);
                    result = new CSTypeBuilder() {
                        Name = primitiveBaseContract.DeserializedType,
                        IsNullable = primitiveBaseContract.DeserializedType.IsValueType && contract.IsOptional
                    };

                } else {
                    result = contract.Name;
                }

                return result;
            }
            #endregion

            #region TObject Overrides
            protected override object Substitute(TContext context, object target) {
                if (target is XsContract)
                    return ContractToCSharp((XsContract)target);

                if (target is Type)
                    return CSSubstitution.SubstituteType(context, (Type)target);

                return target;
            }
            #endregion
        }
        #endregion

        #region Static Internal Data Members
        internal static bool IsDocs;
        internal static bool UseGroups;
        #endregion

        #region Static Internal Members
        internal static void Generate(string dllPath, string docPath, string csPath) {
            var path = Path.Combine(Environment.CurrentDirectory, dllPath);
            var dir = Path.GetDirectoryName(path);
            var dll = Assembly.LoadFile(path);

            Program.InitializeAppDomain(dir);
            DocumentationLoader.Load(docPath);

            var assembly = XsAssembly.GetAssembly(dll);

            var code = Client.Generate(assembly).ToString();

            code = code.Replace("Version.", "King.Service.Version.");

            using (var file = new StreamWriter(csPath, false))
                file.WriteLine(code);
        }
        internal static object Generate(XsAssembly assembly) {

            var ns = (XNamespace)"http://service.adify.com/infoset";
            var entity = assembly.GetContractOrNull("Entity");
            var contracts =
               (from o in XsLoader.Contracts()
                where o.Namespace == ns
                orderby o.Name
                select o).ToArray();
            var attributeSchema = assembly.AttributeSchema;
            var contractSchema = assembly.ContractSchema;

            var members = contracts.SelectMany(o => o.Members()).ToArray();
            var entityMembers = members.Where(o => o.Contract.IsDerivationOf(entity)).ToArray();
            if (entityMembers.Any())
                throw new ArgumentException();

            var code
                = new XsContractToCSType() {
                    new TDoubleLineJoin() {
                        new CSUsingNamespace() {
                            "System",
                            "System.Collections",
                            "System.Collections.Generic",
                            "System.Reflection",
                            "System.Xml.Linq",
                            "System.Runtime.InteropServices",
                            "System.ComponentModel",
                            "System.Linq",
                            "System.Diagnostics",
                            "King",
                            "King.Client",
                            "King.Infoset",
                            "King.Infoset.Schema",
                            "King.Infoset.Entity",
                            "King.Infoset.Serialization",
                            "King.Open.Reflection",
                        },

                        new CSNamespace("King.Service") {
                            new TDoubleLine() {

                                new CSRegion("Complex Contracts (Entities)") {
                                    from o in contracts
                                    where o.IsEntity()
                                    select o.ToCSharp()
                                },

                                new CSRegion("Complex Contracts (EntitieRefs)") {
                                    from o in contracts
                                    where o.IsEntityRef()
                                    select o.ToCSharp()
                                },

                                new CSRegion("Group Contracts") {
                                    from o in contracts
                                    where o.IsGroup
                                    select o.ToCSharp()
                                },

                                new CSRegion("Complex Contracts (Abstract)") {
                                    from o in contracts
                                    where o.IsComplex && o.IsAbstract && !o.IsEntityRef() && !o.IsEntity()
                                    select o.ToCSharp()
                                },
                                
                                new CSRegion("Complex Contracts") {
                                    from o in contracts
                                    where o.IsComplex 
                                    where o.IsComplex && !o.IsAbstract && !o.IsEntityRef() && !o.IsEntity()
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (String)") {
                                    from o in contracts
                                    where o.IsString && !o.IsPrimitive
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Decimal)") {
                                    from o in contracts
                                    where o.IsDecimal && !o.IsPrimitive
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Constants)") {
                                    from o in contracts
                                    where o.IsConstant
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Flags)") {
                                    from o in contracts
                                    where o.IsEnum && o.IsFlags
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Enum)") {
                                    from o in contracts
                                    where o.IsEnum && !o.IsFlags
                                    select o.ToCSharp()
                                },

                                new CSRegion("Union Contracts") {
                                    from o in contracts
                                    where o.IsUnion
                                    select o.ToCSharp()
                                },
                                
                                ////new CSRegion("Primitive Data Contracts") {
                                ////    from o in contracts
                                ////    where o.IsPrimitive
                                ////    select o.ToCSharp()
                                ////},

                                new CSRegion("Annotations") {
                                    from o in contracts
                                    where o.IsAnnotation
                                    where o.Namespace == contractSchema.Namespace
                                    orderby o.Name
                                    select o.ToCSharp()
                                },

                                //KingServiceToCSharp(entity),
                            }
                        }
                    }
                };

            return code.Evaluate();
        }
        private static object ToCSharp(this XsContract contract) {
            return Contract.ToCSharp(contract);
        }
        internal static IEnumerable<string> DecomposeCamelCaseIdentifier(string identifier) {
            if (identifier.ToCharArray().Count(o => char.IsUpper(o)) <= 1)
                yield break;

            var split = string.Empty;
            foreach (var c in identifier.ToCharArray()) {
                if ((char.IsUpper(c) || char.IsDigit(c)) && !string.IsNullOrEmpty(split)) {
                    yield return split;
                    split = string.Empty;
                }

                if (!char.IsDigit(c))
                    split += c;
            }

            if (!string.IsNullOrEmpty(split))
                yield return split;
        }
        #endregion

        #region Static Private Classes
        private static object KingServiceToCSharp(XsContract entity) {
            throw new NotImplementedException();
            //if (IsDocs)
            //    return null;

            //object dataMembers = null;

            //var result = new CSRegion("King Client") {
            //    new DoubleNewLineJoin() {
            //        new CSClass() {                                        
            //            Visibility = CSVisibility.Public,
            //            IsPartial = true,
            //            Name = "KingClientSession",
            //            BaseType = "ClientSession",

            //            Members = new DoubleNewLine() {
            //                new CSRegion("Privte Data Members") {
            //                    from d in XsLoader.Contracts()
            //                    where d.IsDerivationOf(entity)
            //                    orderby d.Name
            //                    select new CSField() {
            //                        Visibility = CSVisibility.Private,
            //                        Type = "{0}EntityType".Substitute(d.Name),
            //                        Name = "m_{0}EntityType".Substitute(d.Name.ToLowerFirst(), d.Name)
            //                    }
            //                },

            //                new CSRegion("Public Members") {
            //                    from d in XsLoader.Contracts()
            //                    where d.IsDerivationOf(entity)
            //                    orderby d.Name
            //                    select new CSProperty() {
            //                        Name = d.Name,
            //                        Visibility = CSVisibility.Public,
            //                        Type = "{0}EntityType".Substitute(d.Name),
            //                        Getter = ("if (m_{0}EntityType == null)" + Environment.NewLine +
            //                                  "    m_{0}EntityType = new {1}EntityType(this);" + Environment.NewLine +
            //                                  "return m_{0}EntityType;")
            //                                  .Substitute(d.Name.ToLowerFirst(), d.Name)
            //                    }
            //                }
            //            }
            //        },

            //        new NewLineJoin() {
            //            from d in XsLoader.Contracts()
            //            where d.IsDerivationOf(entity)
            //            orderby d.Name
            //            let name = "{0}EntityType".Substitute(d.Name)
            //            let operations = 
            //                Operation.OperationsToCSharp(
            //                    from o in d.DeclaredOperations()
            //                    where o.IsStatic
            //                    select o, out dataMembers)
            //            select new CSClass() {
            //                Visibility = CSVisibility.Public,
            //                IsPartial = true,
            //                BaseType = "KingEntityType<{0}>".Substitute(d.Name),
            //                Name = name,

            //                Members = new DoubleNewLine() {

            //                    dataMembers,

            //                    new CSRegion("Constructor") {
            //                        new CSConstructor() {
            //                            Visibility = CSVisibility.Internal,
            //                            Name = name,
            //                            Parameters = new CSParameter("ClientSession", "clientSession"),
            //                            BaseConstructor = "clientSession"
            //                        }
            //                    },

            //                    operations
            //                }
            //            }
            //        }
            //    }
            //};

            //return result;
        }
        private static class Attribute {
            private class ArgumentEx {
                internal AttributeParameter Info;
                internal object Value;
            }
            private class AttributeEx {
                internal AttributeInfo Info;
                internal IEnumerable<ArgumentEx> Arguments;
            }
            private static IEnumerable<AttributeEx> InjectAttributes(XsObject obj) {
                var result = new List<AttributeEx>();

                // if we have a parameter which does not have an XsParameterAttribute already applied...
                var isParameter = obj is XsParameter;
                if (isParameter && !obj.IsDefined<XsParameterAttribute>()) {

                    // ...which has a ClientType...
                    var parameter = (XsParameter)obj;
                    var contract = parameter.Contract;
                    if (contract.ElementContract != null)
                        contract = contract.ElementContract.ContstraintsCommonBaseContract;

                    if (contract.ClientType != null) {

                        // ... then inject XsParameter[Contract = typeof(ClientType)]
                        var attributeInfo = AttributeInfo.GetAttributeInfo(typeof(XsParameterAttribute));

                        var parameterAttribute = new AttributeEx() {
                            Info = attributeInfo,
                            Arguments = new[] {
                                new ArgumentEx() {
                                    Info = attributeInfo.Parameters.Single(o => o.Name == "Contract"),
                                    Value = new CSTypeOf(contract.Name)
                                }
                            }
                        };
                        result.Add(parameterAttribute);
                    }
                }

                return result;
            }
            private static IEnumerable<ArgumentEx> InjectArguments(AttributeData data, XsObject obj, int order, string name) {
                var info = data.AttributeInfo;

                if (obj is XsContract) {
                    var contract = (XsContract)obj;
                    if (contract.ClientType != null && info.Type.IsSubclassOfOrIs(typeof(XsContractAttribute)))
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "DeserializedType"),
                            Value = contract.ClientType.Assembly == typeof(object).Assembly ?
                                (object)new CSTypeOf(contract.ClientType) : contract.ClientType
                        };
                }

                if (obj is XsEnum) {
                    var enumValue = (XsEnum)obj;
                    if (enumValue.ClientEnumValue != null)
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "DeserializedValue"),
                            Value = new CSAttributeValue(enumValue.ClientEnumValue.Value)
                        };
                }

                var isMember = info.Type == typeof(XsMemberAttribute);
                var isParameter = info.Type == typeof(XsParameterAttribute);

                if (isMember) {
                    if (order != 0)
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "Order"),
                            Value = order
                        };

                    if (name != null)
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "Name"),
                            Value = new CSString(name)
                        };
                }

                if (isMember || isParameter) {
                    var member = (XsLocation)obj;
                    var contract = info.NamedParameters.Single(o => o.Name == "Contract");
                    if (member.Contract.ClientType != null) {
                        var value = member.Contract.MetadataType;
                        yield return new ArgumentEx() {
                            Info = contract,
                            Value = member.Contract.MetadataType
                        };
                    }
                }
            }
            private static bool FilterArgument(AttributeArgument argument, XsObject obj) {
                var memberInfo = argument.MemberInfo;
                var type = memberInfo.DeclaringType;

                if (type.IsSubclassOfOrIs<XsObjectAttribute>()) {
                    if (!memberInfo.IsDefined("XsObjectMemberAttribute"))
                        return false;
                    if (argument.Name == "MustDeriveByRestriction")
                        return false;
                    if (argument.Name == "IsRestriction")
                        return false;
                    if (argument.Name == "UseTypedObject")
                        return false;
                    if (argument.Name == "Pattern")
                        return false;
                    if (argument.Name == "DeserializedValue")
                        return false;
                    if (argument.Name == "Contract" && obj is XsMember) {
                        var contract = ((XsMember)obj).Contract;
                        if (contract.IsEnum)
                            return false;
                        if (contract.IsSimple)
                            return true;
                        if (contract.ClientType != null)
                            return false;
                    } if (argument.Name == "DeserializedType") {
                        var isPrimitive = argument.AttributeData.NamedArguments
                            .Where(o => o.Name == "IsPrimitive")
                            .Select(o => (bool)o.Value).SingleOrDefault();
                        return isPrimitive;
                    }
                    if (type.IsSubclassOfOrIs<XsMemberAttribute>() && argument.Name == "Order")
                        return false;
                    if (type.IsSubclassOfOrIs<XsSimpleContractAttribute>())
                        return false;
                } else if (type.IsDefined<XsAnnotationContractAttribute>()) {
                    if (!memberInfo.IsDefined<XsMemberAttribute>())
                        return false;
                }

                return true;
            }
            private static bool FilterAttribute(AttributeData attribute, XsContract contract) {
                // IsDeriveByRestriction is mapped to a base type with virtual properties for all common members
                if (contract != null && contract.IsDeriveByRestriction)
                    return false;

                var type = attribute.Type;

                if (type.IsSubclassOfOrIs<XsObjectAttribute>())
                    return true;

                if (type.IsDefined<XsAnnotationContractAttribute>())
                    return true;

                var knownAttributes = new[] {
                    typeof(FlagsAttribute),
                    typeof(AttributeUsageAttribute),
                    typeof(MaskAttribute),
                };

                if (knownAttributes.Contains(type))
                    return true;

                return false;
            }
            internal static IEnumerable<object> ToCSharp(XsObject info) {
                return ToCSharp(info, null, 0, null);
            }
            internal static IEnumerable<object> ToCSharp(XsObject info, XsContract contract, int order, string name) {

                // attribute target
                var target = CSAttributeGroupTarget.None;
                if (info is XsParameter && ((XsParameter)info).IsReturnParameter)
                    target = CSAttributeGroupTarget.Return;

                // filter, copy, and inject attributes and arguments
                var attributes =
                   (from o in info.AttributeProvider.GetAttributeData()
                    // filter attributes
                    where FilterAttribute(o, contract)
                    select new AttributeEx() {
                        Info = o.AttributeInfo,
                        Arguments =
                           (from argument in o.Arguments
                            // filter arguments
                            where FilterArgument(argument, info)
                            select new ArgumentEx() {
                                Info = argument.Parameter,
                                Value = new CSAttributeValue(argument.Value)
                                // inject arguments
                            }).Union(InjectArguments(o, info, order, name))
                            .ToArray()
                    }).Union(InjectAttributes(info)).ToArray();

                // order attributes
                var assemblyOrder = new[] {
                    typeof(FlagsAttribute).Assembly,                // mscorlib
                    typeof(MaskAttribute).Assembly,                 // King.Extensions
                    typeof(XsObjectAttribute).Assembly,             // King.Infoset
                    typeof(NeverReturnedAttribute).Assembly,        // King.Infoset.Entity
                };
                var sorted = attributes.OrderBy(attribute => AttributeInfo.OrderByKey(attribute.Info, assemblyOrder)).ToArray();

                // group attributes
                var grouped = sorted.GroupBy(attribute => AttributeInfo.GroupByKey(attribute.Info));
                grouped = grouped.Reverse().ToArray();

                // format arguments
                var result =
                   (from attributeGroup in grouped
                    select new CSAttributeGroup(target) {
                        from attribute in attributeGroup
                        select new CSAttribute(attribute.Info.Name) {
                            from argument in attribute.Arguments
                            let value = argument.Value
                            where value != null
                            // order arguments
                            orderby AttributeParameter.OrderByKey(argument.Info)
                            select argument.Info.IsConstructorParameter ? 
                                value : new CSNamedArgument(argument.Info.Name, value),
                        }
                    });

                return result.ToArray();
            }
            internal static object DefaultValueToCSharp(XsMember member) {
                var data = member.AttributeProvider.GetAttributeData();
                var defaultOnCreate = data.Single(o => o.Name == "DefaultOnCreate");
                var defaultArgument = defaultOnCreate.ConstructorArguments.Single();
                var result = defaultArgument.Value;
                return result;
            }
        }
        private static class Operation {
            internal static string OrderBy(string name) {
                var words = DecomposeCamelCaseIdentifier(name.TrimEnd('s'));
                if (words.None())
                    return "_" + name;

                var order = new[] {
                "Check",
                "Get",
                "Set",
                "Create",
                "Add",
                "Remove",
            }.ToList();

                var result =
                    words.Skip(1).StringJoin() +
                    order.IndexOf(words.First()) +
                    words.First();
                return result;
            }
            internal static object ToCSharp(XsOperation operation, CSVisibility visibility) {
                var parameters = operation.Parameters().Select(o => ParameterToCSharp(o));
                if (operation.IsStatic)
                    parameters = new object[] { 
                        new CSParameter("ClientSession", "session") {
                            Attributes = new CSAttribute("XsRuntimeParameter"),
                        }
                    }.Concat(parameters);

                var returnParameter = operation.ReturnParameter;

                var code =
                    new CSMethod() {
                        Documentation = new TJoin(" ") { operation.Summary,
                            (operation.MethodInfo.IsNotImplemented() ? "Not yet implemented." : null)
                        },
                        Attributes = new object[] { 
                        Attribute.ToCSharp(operation),
                        returnParameter == null ? null : Attribute.ToCSharp(returnParameter),
                    },

                        IsStatic = operation.IsStatic,
                        Visibility = visibility,
                        Name = operation.Name,
                        Returns = returnParameter != null ? ParameterToCSharp(returnParameter) : new CSParameter(typeof(void)),
                        Parameters = parameters,
                        Body = EmitOperationBody(operation),
                        IsVirtual = !operation.IsOverride && operation.IsVirtual,
                        IsOverride = operation.IsOverride,
                    };

                return code;
            }
            internal static object RelationshipToCSharp(string name, XsContract contract) {
                var result =
                    new CSProperty() {
                        Visibility = CSVisibility.Public,
                        Name = name,
                        Type = new CSTypeBuilder() {
                            Name = "ClientSet",
                            GenericArguments = contract.ElementContract
                        },
                        GetterBody = new TSubstitute(
                                "if (m_{0} == null)" + Environment.NewLine +
                                "    m_{0} = new ClientSet<{2}>(this, {1});" + Environment.NewLine +
                                "return m_{0};",
                            name.ToLowerFirst(),
                            new CSString(name),
                            contract.ElementContract)
                    };

                return result;
            }
            private static object ParameterToCSharp(XsParameter parameter) {
                var possibleContracts = parameter.Contract.Constraints();

                var contract = !parameter.IsParams ?
                            parameter.Contract :
                            possibleContracts.Count() > 1 ?
                                XsLoader.ObjectContract :
                                possibleContracts.Single();

                if (contract.IsSimple && !contract.IsList)
                    contract = contract.ToLinkList(o => o.BaseContract).First(o => o.IsPrimitive);

                return new CSParameter(
                    parameter.Contract,
                    parameter.Name) {
                        Documentation = parameter.Summary,
                        Name = parameter.Name,
                        Type = !parameter.IsParams ?
                            (object)contract :
                            new CSTypeBuilder() {
                                Name = contract,
                                IsArray = true
                            },
                        IsParams = parameter.IsParams,
                        Attributes = parameter.IsReturnParameter ? null : Attribute.ToCSharp(parameter),
                    };
            }
            private static object EmitOperationBody(XsOperation operation) {
                var type = operation.IsStatic ? "typeof(" + operation.DeclaringContract.Name + ")" : "GetType()";
                var varContract = "var contract = XsLoader.GetContract(" + type + ");";
                var varOperation = "var operation = contract.GetOperation(MethodInfo.GetCurrentMethod());";

                var arguments = "operation";
                arguments += operation.IsStatic ? ", null" : ", this";
                arguments += operation.Parameters()
                    .Select(o => o.Name)
                    .StringJoin(", new object[] { ", ", ", " }");

                var sessionInvoke = operation.IsStatic ?
                    "session.Invoke" :
                    "ClientSession.GetSession(this).Invoke";

                object result;
                if (operation.ReturnParameter == null) {
                    result = sessionInvoke + "({0});".Substitute(arguments);
                } else {
                    if (operation.ReturnParameter.Contract.IsEnumeration) {
                        result = new TSubstitute(
                            "var result = ((IEnumerable)" + sessionInvoke + "({0}));" + Environment.NewLine +
                            "if (result == null) return Enumerable.Empty<{1}>();" + Environment.NewLine +
                            "return result.Cast<{1}>();",
                            arguments, operation.ReturnParameter.Contract.ElementContract);
                    } else {
                        result = new TSubstitute("return ({0})" + sessionInvoke + "({1});",
                            operation.ReturnParameter.Contract, arguments);
                    }
                }

                var comment = "// code:King.{0}.{1} ".Substitute(operation.DeclaringContract.Name, operation.Name);

                return new TSingleLineJoin() { comment, varContract, varOperation, result };
            }
        }
        private static class Member {
            internal class ClientMember {

                #region Constructor
                internal ClientMember(XsMember member, XsContract contract, int order, bool isVirtual, bool isOverride, bool isNew) {
                    Member = member;
                    Contract = contract;
                    Order = order;
                    IsVirtual = isVirtual;
                    IsOverride = isOverride;
                    IsNew = isNew;
                    Type = member.Contract;
                    FieldName = contract.IsEntity() ? "m_" + member.Name.ToLowerFirst() : member.Name;
                }
                #endregion

                #region Internal Data Members
                internal XsMember Member;
                internal XsContract Contract;
                internal string FieldName;
                internal int Order;
                internal bool IsVirtual;
                internal bool IsOverride;
                internal bool IsNew;
                internal object Type;
                #endregion
            }
            internal static object ToField(ClientMember clientMember) {

                var member = clientMember.Member;
                var contract = clientMember.Contract;
                var isNew = clientMember.IsNew;
                var isVirtual = clientMember.IsVirtual;
                var isOverride = clientMember.IsOverride;
                var order = clientMember.Order;
                var fieldName = clientMember.FieldName;

                object getter = null;
                object setter = null;

                if (isNew) {
                    getter = new object[] { "return (", member.Contract, ")base.", fieldName, ";" };
                    setter = "base." + fieldName + " = value;";
                }

                var result =
                    new CSProperty() {
                        Visibility = CSVisibility.Internal,
                        Attributes = Attribute.ToCSharp(member, contract, order, member.Name),
                        IsNew = isNew,
                        IsOverride = isOverride,
                        IsVirtual = isVirtual && !isOverride,
                        Name = fieldName,
                        Type = clientMember.Type,
                        GetterBody = getter,
                        SetterBody = setter,
                    };

                return result;
            }
            internal static object ToProperty(ClientMember clientMember) {

                var member = clientMember.Member;
                var contract = clientMember.Contract;
                var fieldName = clientMember.FieldName;

                string getter = null;
                string setter = null;

                if (contract.IsEntity()) {
                    if (member.IsDefined<EntityIdAttribute>() || member.IsDefined<VersionAttribute>()) {
                        getter = "return " + fieldName + ";";
                        setter = fieldName + " = value;";
                    } else {
                        getter = "Initialize(); return " + fieldName + ";";
                        setter = "Initialize(); " + fieldName + " = value;";
                    }
                }

                var pattern = member.Contract.Regex == null ? null : "Must match regex (" + member.Contract.Regex + ").";

                var result =
                    new CSProperty() {
                        Documentation = new TJoin(" ") { member.Summary, pattern },
                        Attributes = contract.IsEntity() ? null : Attribute.ToCSharp(member, contract, clientMember.Order, null),
                        Visibility = CSVisibility.Public,
                        Name = member.Name,
                        Type = clientMember.Type,
                        IsNew = clientMember.IsNew || clientMember.IsOverride,
                        GetterBody = getter,
                        SetterBody = setter,
                    };

                return result;
            }
            internal static object ToDebugProperty(ClientMember clientMember) {
                var contract = clientMember.Contract;
                var name = clientMember.Member.Name;
                var type = clientMember.Type;

                var fieldName = name;
                if (contract.IsEntity() && !contract.IsEntityRef())
                    fieldName = "m_" + fieldName.ToLowerFirst();

                var result = new CSProperty() {
                    Visibility = CSVisibility.Public,
                    Name = name,
                    Type = type,
                    GetterBody = "return m_target." + fieldName + ";"
                };

                return result;
            }
            private static IEnumerable<ClientMember> ToCSharp(
                XsContract contract, XsMember member, int order, bool isField, ref int groupCount) {
                var declaringContract = member.DeclaringContract;

                var isNew = declaringContract.IsRestriction &&
                    member.BaseMember.Contract != member.Contract &&
                    member.BaseMember.MustRestrict;

                var isVirtual = !isNew &&
                    (declaringContract.IsDeriveByRestriction ||
                    (declaringContract.IsRestriction && !member.BaseMember.CanRestrict));

                var isOverride =
                    isVirtual &&
                    declaringContract.IsRestriction &&
                    !member.BaseMember.CanRestrict;

                var _groupCount = groupCount;

                var members = (IEnumerable<XsMember>)new[] { member };
                if (!UseGroups && member.Contract.IsGroup)
                    members = member.Contract.Members().FlattenGroups();

                var result = members.Select(o =>
                    new ClientMember(o, contract, order + _groupCount++, isVirtual, isOverride, isNew)).ToArray();

                groupCount = _groupCount - 1;

                return result;
            }
            private static IEnumerable<ClientMember> ToClientMembers(
                XsContract contract, XsMember member, int order, ref int groupCount) {
                var declaringContract = member.DeclaringContract;

                var isNew = declaringContract.IsRestriction &&
                    member.BaseMember.Contract != member.Contract &&
                    member.BaseMember.MustRestrict;

                var isVirtual = !isNew &&
                    (declaringContract.IsDeriveByRestriction ||
                    (declaringContract.IsRestriction && !member.BaseMember.CanRestrict));

                var isOverride =
                    isVirtual &&
                    declaringContract.IsRestriction &&
                    !member.BaseMember.CanRestrict;

                var _groupCount = groupCount;

                var members = (IEnumerable<XsMember>)new[] { member };
                if (!UseGroups && member.Contract.IsGroup)
                    members = member.Contract.Members().FlattenGroups();

                var result = members.Select(o =>
                    new ClientMember(o, contract, order + _groupCount++, isVirtual, isOverride, isNew)).ToArray();

                groupCount = _groupCount - 1;

                return result;
            }
            internal static IEnumerable<ClientMember> GetDeclaredClientMembers(XsContract contract) {
                var memberCount = 0;
                var groupCount = 0;

                var result =
                   (from o in contract.DeclaredMembers()
                    where !o.CanRestrict || o.MustRestrict
                    from x in Member.ToClientMembers(contract, o, o.IsSimpleContent ? 0 : ++memberCount, ref groupCount)
                    select x).ToArray();

                return result;
            }
        }
        private static class Contract {
            internal static object ToCSharp(XsContract contract) {
                object result = null;

                if (contract.IsGroup) {
                    result = GroupToCSharp(contract);
                } else if (contract.IsComplex) {
                    result = ComplexToCSharp(contract);
                } else if (contract.IsUnion) {
                    result = UnionToCSharp(contract);
                } else if (contract.IsEnum) {
                    result = EnumToCSharp(contract);
                } else if (contract.IsConstant) {
                    result = ConstantToCSharp(contract);
                } else if (contract.IsSimple) {
                    result = SimpleToCSharp(contract);
                } else if (contract.IsAnnotation) {
                    result = AnnotationToCSharp(contract);
                } else {
                    throw new NotSupportedException();
                }

                return result;
            }
            internal static object ToCSDebugProxy(XsContract contract) {

                return new CSClass() {
                    Name = "DebugProxy",
                    Visibility = CSVisibility.Internal,
                    IsSealed = true,
                    Members = new TDoubleLine() {

                        new CSRegion("Private Data Members") {
                            new CSField() {
                                Name = "m_target",
                                Visibility = CSVisibility.Private,
                                Type = new CSTypeBuilder(contract.Name)
                            }
                        },

                        new CSRegion("Constructor") {
                            new CSConstructor() {
                                Name = "DebugProxy",
                                Parameters = new CSParameter() {
                                    Name = "target",
                                    Type = new CSTypeBuilder(contract.Name),
                                },
                                Visibility = CSVisibility.Public,
                                Body = "m_target = target;"
                            }
                        },

                        new CSRegion("Members") {
                            from o in contract.ToLinkList(o => o.BaseContract)
                                      .SelectMany(x => Member.GetDeclaredClientMembers(x).Reverse())
                                      .Distinct(x => x.Member.Name)
                                      .Reverse()
                            select Member.ToDebugProperty(o)
                        }
                    }
                };
            }
            private static object ContractToDocComment(XsContract contract) {
                return contract.Summary;
                //var result = new CSDocSummary(contract.Summary) {
                //    SignatureTypeIn = !IsDocs ? null : new TJoin(", ") { Program.GetSignatureTypeIn(contract).Select(o => o.Name) },
                //    SubClasses = !IsDocs ? null : new TJoin(", ") { Program.GetSubClasses(contract).Select(o => o.Name) },
                //    ContractIn = !IsDocs ? null : new TJoin(", ") { Program.GetContractMemberIn(contract).Select(o => o.Name) },
                //};

                //return result;
            }
            private static object AnnotationToCSharp(XsContract annotation) {
                var requiredMembers =
                   (from o in annotation.Members()
                    where o.IsRequired
                    orderby o.Order
                    select o).ToArray();

                var requiredDeclaredMembers =
                   (from o in annotation.DeclaredMembers()
                    where o.IsRequired
                    orderby o.Order
                    select o).ToArray();

                var optionalMembers =
                   (from o in annotation.Members()
                    where o.IsOptional
                    orderby o.Order
                    select o).ToArray();

                var order = 0;

                var code = new CSClass() {
                    Documentation = ContractToDocComment(annotation),
                    Attributes = Attribute.ToCSharp(annotation),
                    Visibility = CSVisibility.Public,
                    Name = annotation.Name,
                    BaseType = !annotation.BaseContract.IsObject ?
                        (object)annotation.BaseContract : typeof(Attribute),

                    Members = new TDoubleLine() {
                        IsDocs ? null : new CSRegion("Private Data Members") {
                            from o in requiredDeclaredMembers
                            select new CSField() {
                                Visibility = CSVisibility.Private,
                                Type = o.Contract,
                                Name = "m_" + o.Name.ToLowerFirst()
                            }
                        },

                        requiredMembers.None() ? null : new CSRegion("Constructor") {
                            new CSConstructor() {
                                Visibility = CSVisibility.Public,
                                Name = annotation.Name,
                                Parameters = 
                                    from o in requiredMembers
                                    select new CSParameter() {
                                        Type = o.Contract,
                                        Name = o.Name.ToLowerFirst(),
                                    },
                                BaseConstructor = new TJoin(", ") {
                                    from o in requiredMembers
                                    where !requiredDeclaredMembers.Any(x => x.Name == o.Name)
                                    select o.Name.ToLowerFirst()
                                },
                                Body = new TSingleLineJoin() {
                                    from o in requiredDeclaredMembers
                                    select "m_{0} = {0};".Substitute(o.Name.ToLowerFirst())
                                },
                            }
                        },

                        new CSRegion("Public Members") {
                            new TDoubleLineJoin() {
                                from o in requiredDeclaredMembers
                                select new CSProperty() {
                                    Documentation = o.Summary,
                                    Attributes = Attribute.ToCSharp(o),
                                    Visibility = CSVisibility.Public,
                                    Type = o.Contract,
                                    Name = o.Name,
                                    GetterBody = "return m_" + o.Name.ToLowerFirst() + ";",
                                }                        
                            }
                        },

                        new CSRegion("Public Named Members") {
                            new TDoubleLineJoin() {
                               (from o in optionalMembers
                                select new CSProperty() {
                                    Documentation = o.Summary,
                                    Attributes = Attribute.ToCSharp(o, annotation, ++order, null),
                                    Visibility = CSVisibility.Public,
                                    Type = o.Contract.MakeRequired(),
                                    Name = o.Name,
                                }).ToArray()
                            }
                        }
                    }
                };

                return code;
            }
            private static object ComplexToCSharp(XsContract contract) {

                var gets = contract.Operations().Where(o => o.IsDefined<GetAttribute>()).ToArray();
                var baseContract = contract.BaseContract.Name;
                if (contract.BaseContract.IsObject)
                    baseContract = null;

                var defaultMembers =
                    from o in Member.GetDeclaredClientMembers(contract)
                    let member = o.Member
                    where member.IsDefined<DefaultOnCreateAttribute>()
                    select o;

                bool hasDebugProxy = contract.IsComplex && !contract.IsAbstract && !contract.IsEntityRef();
                var debugName = contract.Name;

                var result =
                    new CSClass() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = new object[] {
                            !hasDebugProxy ? null : new CSAttributeGroup() {
                                new CSAttribute("DebuggerTypeProxy") {
                                    new CSArgument(new CSTypeOf(contract.Name + "." + "DebugProxy"))
                                }
                            },
                            Attribute.ToCSharp(contract),
                        },
                        Visibility = contract.ClientType == null ? CSVisibility.Public : CSVisibility.Internal,
                        IsPartial = true,
                        IsAbstract = contract.IsAbstract,
                        Name = contract.Name,
                        BaseType = baseContract,

                        Members = new TDoubleLine() {                            
                            
                            new CSRegion("Definitions") {
                                hasDebugProxy ? ToCSDebugProxy(contract) : null
                            },

                            new CSRegion("Static Public Members (Operations)") {
                                new TDoubleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where o.IsStatic
                                    orderby Operation.OrderBy(o.Name)
                                    select Operation.ToCSharp(o, CSVisibility.Public)
                                }
                            },

                            new CSRegion("Constructor") {
                                new CSConstructor() {
                                    Visibility = CSVisibility.Public,
                                    Name = contract.Name,
                                    Body = new TSingleLineJoin() {
                                        from o in defaultMembers
                                        select new TObjects {
                                            o.FieldName, " = ", new CSAttributeValue(Attribute.DefaultValueToCSharp(o.Member)), ";"
                                        }
                                    }
                                },
                                defaultMembers.None() ? null : new CSMethod() {
                                    Visibility = CSVisibility.Private,
                                    Name = "ClearDefaults",
                                    Body = new TSingleLineJoin() {
                                        from o in defaultMembers
                                        select new TObjects { o.FieldName, " = default(", o.Member.Contract, ");" }
                                    }
                                }
                            },

                            new CSRegion("Private Data Members") {
                                new TSingleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where o.IsDefined<GetAttribute>()
                                    let name = o.Name.SubStringAfter("Get")
                                    select new CSField() {
                                        Visibility = CSVisibility.Private,
                                        Name = "m_" + name.ToLowerFirst(),
                                        Type = new object[] { "ClientSet<", o.ReturnParameter.Contract.ElementContract, ">" }
                                    }
                                }
                            },

                            !contract.IsEntity() ? null : new CSRegion("Private Data Members (Data)") {
                                from o in Member.GetDeclaredClientMembers(contract)
                                //select new TSingleLineJoin(contract.IsDeriveByRestriction) {
                                select new TSingleLineJoin() {
                                    Member.ToField(o)
                                }
                            },

                            new CSRegion("Public Members (Data)") {
                                from o in Member.GetDeclaredClientMembers(contract)
                                //select new TSingleLineJoin(contract.IsEntity()) {
                                select new TSingleLineJoin() {
                                    Member.ToProperty(o)
                                }
                            },

                            new CSRegion("Private Members (Update, Refresh, Relationship Operations)") {
                                new TDoubleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where !o.IsStatic
                                    where o.IsDefined<UpdateAttribute>()    ||
                                          o.IsDefined<RefreshAttribute>()   || 
                                          o.IsDefined<GetAttribute>()       ||
                                          o.IsDefined<CreateAttribute>()    ||
                                          o.IsDefined<SetAttribute>()       ||
                                          o.IsDefined<AddAttribute>()       ||
                                          o.IsDefined<RemoveAttribute>()
                                    orderby Operation.OrderBy(o.Name)
                                    select Operation.ToCSharp(o, CSVisibility.Internal)
                                }
                            },
                            
                            new CSRegion("Public Members (Relationships)") {
                                new TSingleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where !o.IsStatic
                                    where o.IsDefined<GetAttribute>()
                                    let name = o.Name.SubStringAfter("Get")
                                    select Operation.RelationshipToCSharp(
                                        name, o.ReturnParameter.Contract)
                                }
                            },

                            new CSRegion("Public Members (Operations)") {
                                new TDoubleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where !o.IsStatic
                                    where !o.IsDefined<UpdateAttribute>()   &&
                                          !o.IsDefined<RefreshAttribute>()  &&
                                          !o.IsDefined<CreateAttribute>()   &&
                                          !o.IsDefined<GetAttribute>()      &&
                                          !o.IsDefined<SetAttribute>()      &&
                                          !o.IsDefined<AddAttribute>()      &&
                                          !o.IsDefined<RemoveAttribute>()
                                    orderby Operation.OrderBy(o.Name)
                                    select Operation.ToCSharp(o, CSVisibility.Public)
                                }
                            }
                        }
                    };

                return result;
            }
            private static object GroupToCSharp(XsContract contract) {

                var result =
                    new CSStruct() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = CSVisibility.Public,
                        IsPartial = true,
                        Name = contract.Name,

                        Members = new TDoubleLine() {
                            new CSRegion("Data Members") {
                                from o in Member.GetDeclaredClientMembers(contract)
                                select new TDoubleLineJoin() {
                                    Member.ToProperty(o)
                                }
                            },
                        }
                    };

                return result;
            }
            private static object UnionToCSharp(XsContract contract) {

                var result =
                    new CSClass() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = CSVisibility.Public,
                        IsPartial = true,
                        Name = contract.Name,
                    };

                return result;
            }
            private static object EnumToCSharp(XsContract contract) {

                var masks =
                    from o in contract.Masks()
                    let mask = o.SerializedMask
                    select new {
                        Code = new CSEnumField() {
                            Attributes = Attribute.ToCSharp(o),
                            Documentation = o.Summary,
                            Name = o.Name,
                            Initializer = mask.ToCSharpInitializer(),
                        },
                        MemberInfo = (EnumMemberInfo)mask,
                        Orderby = mask.LongValue,
                    };

                var values =
                   (from o in contract.Enums()
                    let enumValue = o.SerializedEnumValue
                    select new {
                        Code = new CSEnumField() {
                            Attributes = Attribute.ToCSharp(o),
                            Documentation = o.Summary,
                            Name = o.Name,
                            Initializer = enumValue.ToCSharpInitializer()
                        },
                        MemberInfo = (EnumMemberInfo)enumValue,
                        Orderby = enumValue.Mask != null ?
                            enumValue.Mask.LongValue :
                            enumValue.IsFlags ?
                            enumValue.LongValue : -1,
                    }).ToArray();

                var enumInfo = EnumInfo.GetEnumInfo(contract.SerializedType);
                var mostBitsFirst =
                   (from o in enumInfo.Members().Distinct(o => o.LongValue.GetBits())
                    let value = o.LongValue
                    orderby value == -1, value.GetBits().Count() descending
                    select value).ToArray();

                var groups =
                    from o in values.Union(masks)
                    group o by mostBitsFirst.FirstOr<long>(x => o.Orderby.IsSubsetValueOf(x), o.Orderby)
                        into o
                        orderby (long)o.Key select o;

                var members =
                    from o in groups
                    select new TSingleLine() {
                        from x in o 
                        orderby x.MemberInfo is MaskValue descending, x.MemberInfo.LongValue
                        select x.Code
                    };

                var result =
                    new CSEnum() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = CSVisibility.Public,
                        Name = contract.Name,
                        //Padding = enumInfo.Members().Select(o => o.Name).MaxOr(o => o.Length, 0),
                        Members = groups.Any(o => o.MoreThanOne()) ? (object)new TDoubleLineJoin() { members } : members,
                        BaseType = Enum.GetUnderlyingType(contract.MetadataType) != typeof(int) ? typeof(long) : null,
                    };

                return result;
            }
            private static object ConstantToCSharp(XsContract contract) {
                var result = new CSClass() {
                    Name = contract.Name,
                    Visibility = CSVisibility.Public,
                    IsStatic = true,
                    IsPartial = true,
                    Members =
                        from o in contract.Constants()
                        select new CSField() {
                            Documentation = ContractToDocComment(contract),
                            Attributes = new CSAttribute(typeof(XsConstantAttribute)),
                            Visibility = CSVisibility.Public,
                            IsStatic = true,
                            Name = o.MetadataName,
                            Initializer = o.SerializedValue is string ? new CSString(o.SerializedValue) : o.SerializedValue,
                            Type = o.MetadataName.GetType(),
                        },
                    Attributes = Attribute.ToCSharp(contract)
                };

                return result;
            }
            private static object SimpleToCSharp(XsContract contract) {
                var result = new CSClass() {
                    Documentation = ContractToDocComment(contract),
                    Attributes = Attribute.ToCSharp(contract),
                    Visibility = CSVisibility.Public,
                    IsPartial = true,
                    Name = contract.Name,
                };

                return result;
            }
        }
        #endregion
    }

    // /docclient King\King\bin\debug\King.dll King\King\King.xml King\King.Client\DocClient.Generated.cs
    [Command]
    internal static class DocClient {

        #region Definitions
        private class XsContractToCSType : TObjects {

            #region Static Private Members
            private static object ContractToCSharp(XsContract contract) {
                object result = contract;

                // ClientType
                if (contract.ClientType != null) {
                    if (contract.ClientContract != null)
                        result = ContractToCSharp(contract.ClientContract);

                    else {
                        var clientType = contract.ClientType;
                        if (clientType.IsValueType && contract.IsOptional)
                            clientType = clientType.MakeNullable();
                        result = clientType;
                    }

                } else if (contract.IsObject) {
                    if (contract.Constraints().None())
                        result = typeof(object);
                    else
                        result = ContractToCSharp(contract.ContstraintsCommonBaseContract);

                } else if (contract.IsUnion) {
                    result = typeof(object);

                } else if (contract.IsEnumeration) {
                    result = new CSTypeBuilder() {
                        Name = typeof(IEnumerable),
                        GenericArguments = ContractToCSharp(contract.ElementContract)
                    };

                } else if (contract.IsEnum) {
                    result = new CSTypeBuilder() {
                        Name = contract.Name,
                        IsNullable = contract.IsOptional,
                    };

                } else if (contract.IsXml) {
                    result = contract.DeserializedType;

                } else if (contract.IsSimple) {
                    var primitiveBaseContract = contract.ToLinkList(o => o.BaseContract).First(o => o.IsPrimitive);
                    result = new CSTypeBuilder() {
                        Name = primitiveBaseContract.DeserializedType,
                        IsNullable = primitiveBaseContract.DeserializedType.IsValueType && contract.IsOptional
                    };

                } else {
                    result = contract.Name;
                }

                return result;
            }
            #endregion

            #region TObject Overrides
            protected override object Substitute(TContext context, object target) {
                if (target is XsContract)
                    return ContractToCSharp((XsContract)target);

                if (target is Type)
                    return CSSubstitution.SubstituteType(context, (Type)target);

                return target;
            }
            #endregion
        }
        #endregion

        #region Static Internal Data Members
        internal static bool IsDocs;
        internal static bool UseGroups;
        #endregion

        #region Static Internal Members
        internal static void Generate(string dllPath, string docPath, string csPath) {
            var path = Path.Combine(Environment.CurrentDirectory, dllPath);
            var dir = Path.GetDirectoryName(path);
            var dll = Assembly.LoadFile(path);

            Program.InitializeAppDomain(dir);
            DocumentationLoader.Load(docPath);

            var assembly = XsAssembly.GetAssembly(dll);

            var code = Generate(assembly).ToString();

            code = code.Replace("Version.", "King.Service.Version.");

            using (var file = new StreamWriter(csPath, false))
                file.WriteLine(code);
        }
        internal static object Generate(XsAssembly assembly) {

            var ns = (XNamespace)"http://service.adify.com/infoset";
            var entity = assembly.GetContractOrNull("Entity");
            var contracts =
               (from o in XsLoader.Contracts()
                where o.Namespace == ns
                orderby o.Name
                select o).ToArray();
            var attributeSchema = assembly.AttributeSchema;
            var contractSchema = assembly.ContractSchema;

            var members = contracts.SelectMany(o => o.Members()).ToArray();
            var entityMembers = members.Where(o => o.Contract.IsDerivationOf(entity)).ToArray();
            if (entityMembers.Any())
                throw new ArgumentException();

            var code
                = new XsContractToCSType() {
                    new TDoubleLineJoin() {
                        new CSUsingNamespace() {
                            "System",
                            "System.Collections",
                            "System.Collections.Generic",
                            "System.Reflection",
                            "System.Xml.Linq",
                            "System.Runtime.InteropServices",
                            "System.ComponentModel",
                            "System.Linq",
                            "System.Diagnostics",
                            "King",
                            "King.Client",
                            "King.Infoset",
                            "King.Infoset.Schema",
                            "King.Infoset.Entity",
                            "King.Infoset.Serialization",
                            "King.Open.Reflection",
                        },

                        new CSNamespace("King.Service") {
                            new TDoubleLine() {

                                new CSRegion("Complex Contracts (Entities)") {
                                    from o in contracts
                                    where o.IsEntity()
                                    select o.ToCSharp()
                                },

                                new CSRegion("Complex Contracts (EntitieRefs)") {
                                    from o in contracts
                                    where o.IsEntityRef()
                                    select o.ToCSharp()
                                },

                                new CSRegion("Group Contracts") {
                                    from o in contracts
                                    where o.IsGroup
                                    select o.ToCSharp()
                                },

                                new CSRegion("Complex Contracts (Abstract)") {
                                    from o in contracts
                                    where o.IsComplex && o.IsAbstract && !o.IsEntityRef() && !o.IsEntity()
                                    select o.ToCSharp()
                                },
                                
                                new CSRegion("Complex Contracts") {
                                    from o in contracts
                                    where o.IsComplex 
                                    where o.IsComplex && !o.IsAbstract && !o.IsEntityRef() && !o.IsEntity()
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (String)") {
                                    from o in contracts
                                    where o.IsString && !o.IsPrimitive
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Decimal)") {
                                    from o in contracts
                                    where o.IsDecimal && !o.IsPrimitive
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Constants)") {
                                    from o in contracts
                                    where o.IsConstant
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Flags)") {
                                    from o in contracts
                                    where o.IsEnum && o.IsFlags
                                    select o.ToCSharp()
                                },

                                new CSRegion("Simple Contracts (Enum)") {
                                    from o in contracts
                                    where o.IsEnum && !o.IsFlags
                                    select o.ToCSharp()
                                },

                                new CSRegion("Union Contracts") {
                                    from o in contracts
                                    where o.IsUnion
                                    select o.ToCSharp()
                                },
                                
                                ////new CSRegion("Primitive Data Contracts") {
                                ////    from o in contracts
                                ////    where o.IsPrimitive
                                ////    select o.ToCSharp()
                                ////},

                                new CSRegion("Annotations") {
                                    from o in contracts
                                    where o.IsAnnotation
                                    where o.Namespace == contractSchema.Namespace
                                    orderby o.Name
                                    select o.ToCSharp()
                                },

                                //KingServiceToCSharp(entity),
                            }
                        }
                    }
                };

            return code.Evaluate();
        }
        private static object ToCSharp(this XsContract contract) {
            return Contract.ToCSharp(contract);
        }
        internal static IEnumerable<string> DecomposeCamelCaseIdentifier(string identifier) {
            if (identifier.ToCharArray().Count(o => char.IsUpper(o)) <= 1)
                yield break;

            var split = string.Empty;
            foreach (var c in identifier.ToCharArray()) {
                if ((char.IsUpper(c) || char.IsDigit(c)) && !string.IsNullOrEmpty(split)) {
                    yield return split;
                    split = string.Empty;
                }

                if (!char.IsDigit(c))
                    split += c;
            }

            if (!string.IsNullOrEmpty(split))
                yield return split;
        }
        #endregion

        #region Static Private Classes
        private static class Attribute {
            private class ArgumentEx {
                internal AttributeParameter Info;
                internal object Value;
            }
            private class AttributeEx {
                internal AttributeInfo Info;
                internal IEnumerable<ArgumentEx> Arguments;
            }
            private static IEnumerable<AttributeEx> InjectAttributes(XsObject obj) {
                var result = new List<AttributeEx>();

                // if we have a parameter which does not have an XsParameterAttribute already applied...
                var isParameter = obj is XsParameter;
                if (isParameter && !obj.IsDefined<XsParameterAttribute>()) {

                    // ...which has a ClientType...
                    var parameter = (XsParameter)obj;
                    var contract = parameter.Contract;
                    if (contract.ElementContract != null)
                        contract = contract.ElementContract.ContstraintsCommonBaseContract;

                    if (contract.ClientType != null) {

                        // ... then inject XsParameter[Contract = typeof(ClientType)]
                        var attributeInfo = AttributeInfo.GetAttributeInfo(typeof(XsParameterAttribute));

                        var parameterAttribute = new AttributeEx() {
                            Info = attributeInfo,
                            Arguments = new[] {
                                new ArgumentEx() {
                                    Info = attributeInfo.Parameters.Single(o => o.Name == "Contract"),
                                    Value = new CSTypeOf(contract.Name)
                                }
                            }
                        };
                        result.Add(parameterAttribute);
                    }
                }

                return result;
            }
            private static IEnumerable<ArgumentEx> InjectArguments(AttributeData data, XsObject obj, int order, string name) {
                var info = data.AttributeInfo;

                if (obj is XsContract) {
                    var contract = (XsContract)obj;
                    if (contract.ClientType != null && info.Type.IsSubclassOfOrIs(typeof(XsContractAttribute)))
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "DeserializedType"),
                            Value = contract.ClientType.Assembly == typeof(object).Assembly ?
                                (object)new CSTypeOf(contract.ClientType) : contract.ClientType
                        };
                }

                if (obj is XsEnum) {
                    var enumValue = (XsEnum)obj;
                    if (enumValue.ClientEnumValue != null)
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "DeserializedValue"),
                            Value = new CSAttributeValue(enumValue.ClientEnumValue.Value)
                        };
                }

                var isMember = info.Type == typeof(XsMemberAttribute);
                var isParameter = info.Type == typeof(XsParameterAttribute);

                if (isMember) {
                    if (order != 0)
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "Order"),
                            Value = order
                        };

                    if (name != null)
                        yield return new ArgumentEx() {
                            Info = info.NamedParameters.Single(o => o.Name == "Name"),
                            Value = new CSString(name)
                        };
                }

                if (isMember || isParameter) {
                    var member = (XsLocation)obj;
                    var contract = info.NamedParameters.Single(o => o.Name == "Contract");
                    if (member.Contract.ClientType != null) {
                        var value = member.Contract.MetadataType;
                        yield return new ArgumentEx() {
                            Info = contract,
                            Value = member.Contract.MetadataType
                        };
                    }
                }
            }
            private static bool FilterArgument(AttributeArgument argument, XsObject obj) {
                var memberInfo = argument.MemberInfo;
                var type = memberInfo.DeclaringType;

                if (type.IsSubclassOfOrIs<XsObjectAttribute>()) {
                    if (!memberInfo.IsDefined("XsObjectMemberAttribute"))
                        return false;
                    if (argument.Name == "MustDeriveByRestriction")
                        return false;
                    if (argument.Name == "IsRestriction")
                        return false;
                    if (argument.Name == "UseTypedObject")
                        return false;
                    if (argument.Name == "Pattern")
                        return false;
                    if (argument.Name == "DeserializedValue")
                        return false;
                    if (argument.Name == "Contract" && obj is XsMember) {
                        var contract = ((XsMember)obj).Contract;
                        if (contract.IsEnum)
                            return false;
                        if (contract.IsSimple)
                            return true;
                        if (contract.ClientType != null)
                            return false;
                    } if (argument.Name == "DeserializedType") {
                        var isPrimitive = argument.AttributeData.NamedArguments
                            .Where(o => o.Name == "IsPrimitive")
                            .Select(o => (bool)o.Value).SingleOrDefault();
                        return isPrimitive;
                    }
                    if (type.IsSubclassOfOrIs<XsMemberAttribute>() && argument.Name == "Order")
                        return false;
                    if (type.IsSubclassOfOrIs<XsSimpleContractAttribute>())
                        return false;
                } else if (type.IsDefined<XsAnnotationContractAttribute>()) {
                    if (!memberInfo.IsDefined<XsMemberAttribute>())
                        return false;
                }

                return true;
            }
            private static bool FilterAttribute(AttributeData attribute, XsContract contract) {
                // IsDeriveByRestriction is mapped to a base type with virtual properties for all common members
                if (contract != null && contract.IsDeriveByRestriction)
                    return false;

                var type = attribute.Type;

                if (type.IsSubclassOfOrIs<XsObjectAttribute>())
                    return true;

                if (type.IsDefined<XsAnnotationContractAttribute>())
                    return true;

                var knownAttributes = new[] {
                    typeof(FlagsAttribute),
                    typeof(AttributeUsageAttribute),
                    typeof(MaskAttribute),
                };

                if (knownAttributes.Contains(type))
                    return true;

                return false;
            }
            internal static IEnumerable<object> ToCSharp(XsObject info) {
                return ToCSharp(info, null, 0, null);
            }
            internal static IEnumerable<object> ToCSharp(XsObject info, XsContract contract, int order, string name) {

                // attribute target
                var target = CSAttributeGroupTarget.None;
                if (info is XsParameter && ((XsParameter)info).IsReturnParameter)
                    target = CSAttributeGroupTarget.Return;

                // filter, copy, and inject attributes and arguments
                var attributes =
                   (from o in info.AttributeProvider.GetAttributeData()
                    // filter attributes
                    where FilterAttribute(o, contract)
                    select new AttributeEx() {
                        Info = o.AttributeInfo,
                        Arguments =
                           (from argument in o.Arguments
                            // filter arguments
                            where FilterArgument(argument, info)
                            select new ArgumentEx() {
                                Info = argument.Parameter,
                                Value = new CSAttributeValue(argument.Value)
                                // inject arguments
                            }).Union(InjectArguments(o, info, order, name))
                            .ToArray()
                    }).Union(InjectAttributes(info)).ToArray();

                // order attributes
                var assemblyOrder = new[] {
                    typeof(FlagsAttribute).Assembly,                // mscorlib
                    typeof(MaskAttribute).Assembly,                 // King.Extensions
                    typeof(XsObjectAttribute).Assembly,             // King.Infoset
                    typeof(NeverReturnedAttribute).Assembly,        // King.Infoset.Entity
                };
                var sorted = attributes.OrderBy(attribute => AttributeInfo.OrderByKey(attribute.Info, assemblyOrder)).ToArray();

                // group attributes
                var grouped = sorted.GroupBy(attribute => AttributeInfo.GroupByKey(attribute.Info));
                grouped = grouped.Reverse().ToArray();

                // format arguments
                var result =
                   (from attributeGroup in grouped
                    select new CSAttributeGroup(target) {
                        from attribute in attributeGroup
                        select new CSAttribute(attribute.Info.Name) {
                            from argument in attribute.Arguments
                            let value = argument.Value
                            where value != null
                            // order arguments
                            orderby AttributeParameter.OrderByKey(argument.Info)
                            select argument.Info.IsConstructorParameter ? 
                                value : new CSNamedArgument(argument.Info.Name, value),
                        }
                    });

                return result.ToArray();
            }
            internal static object DefaultValueToCSharp(XsMember member) {
                var data = member.AttributeProvider.GetAttributeData();
                var defaultOnCreate = data.Single(o => o.Name == "DefaultOnCreate");
                var defaultArgument = defaultOnCreate.ConstructorArguments.Single();
                var result = defaultArgument.Value;
                return result;
            }
        }
        private static class Operation {
            internal static string OrderBy(string name) {
                var words = DecomposeCamelCaseIdentifier(name.TrimEnd('s'));
                if (words.None())
                    return "_" + name;

                var order = new[] {
                "Check",
                "Get",
                "Set",
                "Create",
                "Add",
                "Remove",
            }.ToList();

                var result =
                    words.Skip(1).StringJoin() +
                    order.IndexOf(words.First()) +
                    words.First();
                return result;
            }
            internal static object ToCSharp(XsOperation operation, CSVisibility visibility) {
                var parameters = operation.Parameters().Select(o => ParameterToCSharp(o));
                if (operation.IsStatic)
                    parameters = new object[] { 
                        new CSParameter("ClientSession", "session") {
                            Attributes = new CSAttribute("XsRuntimeParameter"),
                        }
                    }.Concat(parameters);

                var returnParameter = operation.ReturnParameter;

                var code =
                    new CSMethod() {
                        Documentation = new TJoin(" ") { operation.Summary,
                            (operation.MethodInfo.IsNotImplemented() ? "Not yet implemented." : null)
                        },
                        Attributes = new object[] { 
                        Attribute.ToCSharp(operation),
                        returnParameter == null ? null : Attribute.ToCSharp(returnParameter),
                    },

                        IsExtern = true,
                        IsStatic = operation.IsStatic,
                        Visibility = visibility,
                        Name = operation.Name,
                        Returns = returnParameter != null ? ParameterToCSharp(returnParameter) : new CSParameter(typeof(void)),
                        Parameters = parameters,
                        IsVirtual = !operation.IsOverride && operation.IsVirtual,
                        IsOverride = operation.IsOverride,
                    };

                return code;
            }
            internal static object RelationshipToCSharp(string name, XsContract contract) {
                var result =
                    new CSProperty() {
                        Visibility = CSVisibility.Public,
                        IsExtern = true,
                        Name = name,
                        Type = new CSTypeBuilder() {
                            Name = "ClientSet",
                            GenericArguments = contract.ElementContract
                        },
                    };

                return result;
            }
            private static object ParameterToCSharp(XsParameter parameter) {
                var possibleContracts = parameter.Contract.Constraints();

                var contract = !parameter.IsParams ?
                            parameter.Contract :
                            possibleContracts.Count() > 1 ?
                                XsLoader.ObjectContract :
                                possibleContracts.Single();

                if (contract.IsSimple && !contract.IsList)
                    contract = contract.ToLinkList(o => o.BaseContract).First(o => o.IsPrimitive);

                return new CSParameter(
                    parameter.Contract,
                    parameter.Name) {
                        Documentation = parameter.Summary,
                        Name = parameter.Name,
                        Type = !parameter.IsParams ?
                            (object)contract :
                            new CSTypeBuilder() {
                                Name = contract,
                                IsArray = true
                            },
                        IsParams = parameter.IsParams,
                        Attributes = parameter.IsReturnParameter ? null : Attribute.ToCSharp(parameter),
                    };
            }
        }
        private static class Member {
            internal class ClientMember {

                #region Constructor
                internal ClientMember(XsMember member, XsContract contract, int order, bool isVirtual, bool isOverride, bool isNew) {
                    Member = member;
                    Contract = contract;
                    Order = order;
                    IsVirtual = isVirtual;
                    IsOverride = isOverride;
                    IsNew = isNew;
                    Type = member.Contract;
                    FieldName = contract.IsEntity() ? member.Name.ToLowerFirst() : member.Name;
                }
                #endregion

                #region Internal Data Members
                internal XsMember Member;
                internal XsContract Contract;
                internal string FieldName;
                internal int Order;
                internal bool IsVirtual;
                internal bool IsOverride;
                internal bool IsNew;
                internal object Type;
                #endregion
            }
            internal static object ToField(ClientMember clientMember) {

                var member = clientMember.Member;
                var contract = clientMember.Contract;
                var isNew = clientMember.IsNew;
                var isVirtual = clientMember.IsVirtual;
                var isOverride = clientMember.IsOverride;
                var order = clientMember.Order;
                var fieldName = clientMember.FieldName;

                var result =
                    new CSProperty() {
                        Visibility = CSVisibility.Internal,
                        Attributes = Attribute.ToCSharp(member, contract, order, member.Name),
                        IsNew = isNew,
                        IsOverride = isOverride,
                        IsVirtual = isVirtual && !isOverride,
                        Name = fieldName,
                        Type = clientMember.Type,
                    };

                return result;
            }
            internal static object ToProperty(ClientMember clientMember) {

                var member = clientMember.Member;
                var contract = clientMember.Contract;
                var fieldName = clientMember.FieldName;

                var result =
                    new CSProperty() {
                        Documentation = member.Summary,
                        Attributes = contract.IsEntity() ? null : Attribute.ToCSharp(member, contract, clientMember.Order, null),
                        Visibility = CSVisibility.Public,
                        Name = member.Name,
                        Type = clientMember.Type,
                        IsNew = clientMember.IsNew || clientMember.IsOverride,
                    };

                return result;
            }
            private static IEnumerable<ClientMember> ToCSharp(
                XsContract contract, XsMember member, int order, bool isField, ref int groupCount) {
                var declaringContract = member.DeclaringContract;

                var isNew = declaringContract.IsRestriction &&
                    member.BaseMember.Contract != member.Contract &&
                    member.BaseMember.MustRestrict;

                var isVirtual = !isNew &&
                    (declaringContract.IsDeriveByRestriction ||
                    (declaringContract.IsRestriction && !member.BaseMember.CanRestrict));

                var isOverride =
                    isVirtual &&
                    declaringContract.IsRestriction &&
                    !member.BaseMember.CanRestrict;

                var _groupCount = groupCount;

                var members = (IEnumerable<XsMember>)new[] { member };
                if (!UseGroups && member.Contract.IsGroup)
                    members = member.Contract.Members().FlattenGroups();

                var result = members.Select(o =>
                    new ClientMember(o, contract, order + _groupCount++, isVirtual, isOverride, isNew)).ToArray();

                groupCount = _groupCount - 1;

                return result;
            }
            private static IEnumerable<ClientMember> ToClientMembers(
                XsContract contract, XsMember member, int order, ref int groupCount) {
                var declaringContract = member.DeclaringContract;

                var isNew = declaringContract.IsRestriction &&
                    member.BaseMember.Contract != member.Contract &&
                    member.BaseMember.MustRestrict;

                var isVirtual = !isNew &&
                    (declaringContract.IsDeriveByRestriction ||
                    (declaringContract.IsRestriction && !member.BaseMember.CanRestrict));

                var isOverride =
                    isVirtual &&
                    declaringContract.IsRestriction &&
                    !member.BaseMember.CanRestrict;

                var _groupCount = groupCount;

                var members = (IEnumerable<XsMember>)new[] { member };
                if (!UseGroups && member.Contract.IsGroup)
                    members = member.Contract.Members().FlattenGroups();

                var result = members.Select(o =>
                    new ClientMember(o, contract, order + _groupCount++, isVirtual, isOverride, isNew)).ToArray();

                groupCount = _groupCount - 1;

                return result;
            }
            internal static IEnumerable<ClientMember> GetDeclaredClientMembers(XsContract contract) {
                var memberCount = 0;
                var groupCount = 0;

                var result =
                   (from o in contract.DeclaredMembers()
                    where !o.CanRestrict || o.MustRestrict
                    from x in Member.ToClientMembers(contract, o, o.IsSimpleContent ? 0 : ++memberCount, ref groupCount)
                    select x).ToArray();

                return result;
            }
        }
        private static class Contract {
            internal static object ToCSharp(XsContract contract) {
                object result = null;

                if (contract.IsGroup) {
                    result = GroupToCSharp(contract);
                } else if (contract.IsComplex) {
                    result = ComplexToCSharp(contract);
                } else if (contract.IsUnion) {
                    result = UnionToCSharp(contract);
                } else if (contract.IsEnum) {
                    result = EnumToCSharp(contract);
                } else if (contract.IsConstant) {
                    result = ConstantToCSharp(contract);
                } else if (contract.IsSimple) {
                    result = SimpleToCSharp(contract);
                } else if (contract.IsAnnotation) {
                    result = AnnotationToCSharp(contract);
                } else {
                    throw new NotSupportedException();
                }

                return result;
            }
            private static object ContractToDocComment(XsContract contract) {
                return contract.Summary;
                //var result = new CSDocSummary(contract.Summary) {
                //    SignatureTypeIn = !IsDocs ? null : new TJoin(", ") { Program.GetSignatureTypeIn(contract).Select(o => o.Name) },
                //    SubClasses = !IsDocs ? null : new TJoin(", ") { Program.GetSubClasses(contract).Select(o => o.Name) },
                //    ContractIn = !IsDocs ? null : new TJoin(", ") { Program.GetContractMemberIn(contract).Select(o => o.Name) },
                //};

                //return result;
            }
            private static object AnnotationToCSharp(XsContract annotation) {
                var requiredMembers =
                   (from o in annotation.Members()
                    where o.IsRequired
                    orderby o.Order
                    select o).ToArray();

                var requiredDeclaredMembers =
                   (from o in annotation.DeclaredMembers()
                    where o.IsRequired
                    orderby o.Order
                    select o).ToArray();

                var optionalMembers =
                   (from o in annotation.Members()
                    where o.IsOptional
                    orderby o.Order
                    select o).ToArray();

                var order = 0;

                var code = new CSClass() {
                    Documentation = ContractToDocComment(annotation),
                    Attributes = Attribute.ToCSharp(annotation),
                    Visibility = CSVisibility.Public,
                    Name = annotation.Name,
                    BaseType = !annotation.BaseContract.IsObject ?
                        (object)annotation.BaseContract : typeof(Attribute),

                    Members = new TDoubleLine() {
                        IsDocs ? null : new CSRegion("Private Data Members") {
                            from o in requiredDeclaredMembers
                            select new CSField() {
                                Visibility = CSVisibility.Private,
                                Type = o.Contract,
                                Name = "m_" + o.Name.ToLowerFirst()
                            }
                        },

                        requiredMembers.None() ? null : new CSRegion("Constructor") {
                            new CSConstructor() {
                                Visibility = CSVisibility.Public,
                                Name = annotation.Name,
                                Parameters = 
                                    from o in requiredMembers
                                    select new CSParameter() {
                                        Type = o.Contract,
                                        Name = o.Name.ToLowerFirst(),
                                    },
                                BaseConstructor = new TJoin(", ") {
                                    from o in requiredMembers
                                    where !requiredDeclaredMembers.Any(x => x.Name == o.Name)
                                    select o.Name.ToLowerFirst()
                                },
                                Body = new TSingleLineJoin() {
                                    from o in requiredDeclaredMembers
                                    select "m_{0} = {0};".Substitute(o.Name.ToLowerFirst())
                                },
                            }
                        },

                        new CSRegion("Public Members") {
                            new TDoubleLineJoin() {
                                from o in requiredDeclaredMembers
                                select new CSProperty() {
                                    Documentation = o.Summary,
                                    Attributes = Attribute.ToCSharp(o),
                                    Visibility = CSVisibility.Public,
                                    Type = o.Contract,
                                    Name = o.Name,
                                    GetterBody = "return m_" + o.Name.ToLowerFirst() + ";",
                                }                        
                            }
                        },

                        new CSRegion("Public Named Members") {
                            new TDoubleLineJoin() {
                               (from o in optionalMembers
                                select new CSProperty() {
                                    Documentation = o.Summary,
                                    Attributes = Attribute.ToCSharp(o, annotation, ++order, null),
                                    Visibility = CSVisibility.Public,
                                    Type = o.Contract.MakeRequired(),
                                    Name = o.Name,
                                }).ToArray()
                            }
                        }
                    }
                };

                return code;
            }
            private static object ComplexToCSharp(XsContract contract) {

                var gets = contract.Operations().Where(o => o.IsDefined<GetAttribute>()).ToArray();
                var baseContract = contract.BaseContract.Name;
                if (contract.BaseContract.IsObject)
                    baseContract = null;

                var defaultMembers =
                    from o in Member.GetDeclaredClientMembers(contract)
                    let member = o.Member
                    where member.IsDefined<DefaultOnCreateAttribute>()
                    select o;

                bool hasDebugProxy = contract.IsComplex && !contract.IsAbstract && !contract.IsEntityRef();
                var debugName = contract.Name;

                var result =
                    new CSClass() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = contract.ClientType == null ? CSVisibility.Public : CSVisibility.Internal,
                        IsPartial = true,
                        IsAbstract = contract.IsAbstract,
                        Name = contract.Name,
                        BaseType = baseContract,

                        Members = new TDoubleLine() {                            
                            
                            new CSRegion("Static Public Members (Operations)") {
                                new TDoubleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where o.IsStatic
                                    orderby Operation.OrderBy(o.Name)
                                    select Operation.ToCSharp(o, CSVisibility.Public)
                                }
                            },

                            !contract.IsEntity() ? null : new CSRegion("Private Data Members (Data)") {
                                from o in Member.GetDeclaredClientMembers(contract)
                                //select new TSingleLineJoin(contract.IsDeriveByRestriction) {
                                select new TSingleLineJoin() {
                                    Member.ToField(o)
                                }
                            },

                            new CSRegion("Private Members (Update, Refresh, Relationship Operations)") {
                                new TDoubleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where !o.IsStatic
                                    where o.IsDefined<UpdateAttribute>()    ||
                                          o.IsDefined<RefreshAttribute>()   || 
                                          o.IsDefined<GetAttribute>()       ||
                                          o.IsDefined<CreateAttribute>()    ||
                                          o.IsDefined<SetAttribute>()       ||
                                          o.IsDefined<AddAttribute>()       ||
                                          o.IsDefined<RemoveAttribute>()
                                    orderby Operation.OrderBy(o.Name)
                                    select Operation.ToCSharp(o, CSVisibility.Internal)
                                }
                            },
                            
                            new CSRegion("Public Members (Relationships)") {
                                new TSingleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where !o.IsStatic
                                    where o.IsDefined<GetAttribute>()
                                    let name = o.Name.SubStringAfter("Get")
                                    select Operation.RelationshipToCSharp(
                                        name, o.ReturnParameter.Contract)
                                }
                            },

                            new CSRegion("Public Members (Operations)") {
                                new TDoubleLineJoin() {
                                    from o in contract.DeclaredOperations()
                                    where !o.IsStatic
                                    where !o.IsDefined<UpdateAttribute>()   &&
                                          !o.IsDefined<RefreshAttribute>()  &&
                                          !o.IsDefined<CreateAttribute>()   &&
                                          !o.IsDefined<GetAttribute>()      &&
                                          !o.IsDefined<SetAttribute>()      &&
                                          !o.IsDefined<AddAttribute>()      &&
                                          !o.IsDefined<RemoveAttribute>()
                                    orderby Operation.OrderBy(o.Name)
                                    select Operation.ToCSharp(o, CSVisibility.Public)
                                }
                            }
                        }
                    };

                return result;
            }
            private static object GroupToCSharp(XsContract contract) {

                var result =
                    new CSStruct() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = CSVisibility.Public,
                        IsPartial = true,
                        Name = contract.Name,

                        Members = new TDoubleLine() {
                            new CSRegion("Data Members") {
                                from o in Member.GetDeclaredClientMembers(contract)
                                select new TDoubleLineJoin() {
                                    Member.ToProperty(o)
                                }
                            },
                        }
                    };

                return result;
            }
            private static object UnionToCSharp(XsContract contract) {

                var result =
                    new CSClass() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = CSVisibility.Public,
                        IsPartial = true,
                        Name = contract.Name,
                    };

                return result;
            }
            private static object EnumToCSharp(XsContract contract) {

                var masks =
                    from o in contract.Masks()
                    let mask = o.SerializedMask
                    select new {
                        Code = new CSEnumField() {
                            Attributes = Attribute.ToCSharp(o),
                            Documentation = o.Summary,
                            Name = o.Name,
                            Initializer = mask.ToCSharpInitializer(),
                        },
                        MemberInfo = (EnumMemberInfo)mask,
                        Orderby = mask.LongValue,
                    };

                var values =
                   (from o in contract.Enums()
                    let enumValue = o.SerializedEnumValue
                    select new {
                        Code = new CSEnumField() {
                            Attributes = Attribute.ToCSharp(o),
                            Documentation = o.Summary,
                            Name = o.Name,
                            Initializer = enumValue.ToCSharpInitializer()
                        },
                        MemberInfo = (EnumMemberInfo)enumValue,
                        Orderby = enumValue.Mask != null ?
                            enumValue.Mask.LongValue :
                            enumValue.IsFlags ?
                            enumValue.LongValue : -1,
                    }).ToArray();

                var enumInfo = EnumInfo.GetEnumInfo(contract.SerializedType);
                var mostBitsFirst =
                   (from o in enumInfo.Members().Distinct(o => o.LongValue.GetBits())
                    let value = o.LongValue
                    orderby value == -1, value.GetBits().Count() descending
                    select value).ToArray();

                var groups =
                    from o in values.Union(masks)
                    group o by mostBitsFirst.FirstOr<long>(x => o.Orderby.IsSubsetValueOf(x), o.Orderby)
                        into o
                        orderby (long)o.Key select o;

                var members =
                    from o in groups
                    select new TSingleLine() {
                        from x in o 
                        orderby x.MemberInfo is MaskValue descending, x.MemberInfo.LongValue
                        select x.Code
                    };

                var result =
                    new CSEnum() {
                        Documentation = ContractToDocComment(contract),
                        Attributes = Attribute.ToCSharp(contract),
                        Visibility = CSVisibility.Public,
                        Name = contract.Name,
                        //Padding = enumInfo.Members().Select(o => o.Name).MaxOr(o => o.Length, 0),
                        Members = groups.Any(o => o.MoreThanOne()) ? (object)new TDoubleLineJoin() { members } : members,
                        BaseType = Enum.GetUnderlyingType(contract.MetadataType) != typeof(int) ? typeof(long) : null,
                    };

                return result;
            }
            private static object ConstantToCSharp(XsContract contract) {
                var result = new CSClass() {
                    Name = contract.Name,
                    Visibility = CSVisibility.Public,
                    IsStatic = true,
                    IsPartial = true,
                    Members =
                        from o in contract.Constants()
                        select new CSField() {
                            Documentation = ContractToDocComment(contract),
                            Attributes = new CSAttribute(typeof(XsConstantAttribute)),
                            Visibility = CSVisibility.Public,
                            IsStatic = true,
                            Name = o.MetadataName,
                            Initializer = o.SerializedValue is string ? new CSString(o.SerializedValue) : o.SerializedValue,
                            Type = o.MetadataName.GetType(),
                        },
                    Attributes = Attribute.ToCSharp(contract)
                };

                return result;
            }
            private static object SimpleToCSharp(XsContract contract) {
                var result = new CSClass() {
                    Documentation = ContractToDocComment(contract),
                    Attributes = Attribute.ToCSharp(contract),
                    Visibility = CSVisibility.Public,
                    IsPartial = true,
                    Name = contract.Name,
                };

                return result;
            }
        }
        #endregion
    }

    // /schema KingService\bin\King.Service.dll KingService\King.Service.xml KingService\King.xsd
    [Command]
    internal static class Schema {
#if false
        #region Static Internal Data Members
        internal static bool Docs;
        #endregion

        #region Static Internal Members
        internal static Format ToFormat(object target) {
            return null;
        }
        internal static XmlFormat ToXsd(this XsObject metadata) {
            if (metadata == null)
                return null;

            var pseudoCustomAttributes = new List<XmlAttributeFormat>();

            //throw new NotImplementedException();
            //var customAttributes = 
            //    from o in metadata.Annotations
            //    group o by o.XName into o
            //    orderby o.Key.LocalName
            //    select new XmlAttribute(o.Key, o.StringJoin(" ", s => s.Value));

            if (metadata is XsParameter || metadata is XsOperation) {

                XopFormat xop = null;

                if (metadata is XsParameter) {

        #region metadata is Parameter
                    var parameter = metadata as XsParameter;
                    var contract = parameter.Contract;
                    var isEnumeration = false;
                    if (contract.IsEnumeration && contract.Constraints().Any()) {
                        isEnumeration = true;
                        contract =
                            contract.Constraints().Count() > 1 ? XsLoader.ObjectContract :
                            contract.Constraints().SingleOrDefault() ?? contract;
                    }

                    object typeName = contract.FullName;
                    if (isEnumeration)
                        typeName = new Concat(typeName, "[]").ToString();

                    if (parameter.IsReturnParameter)
                        xop = new XopReturns() { Type = typeName };
                    else
                        xop = new XopParameter() {
                            Name = parameter.Name.ToLowerFirst(),
                            Type = typeName,
                            IsParams = parameter.IsParams
                        };
                    #endregion

                } else if (metadata is XsOperation) {
                    var operation = metadata as XsOperation;
                    xop = ToXsd(operation);
                    xop.Documentation = operation.MethodInfo.IsNotImplemented() ? "Not yet implemented." : null;
                }

                xop.Documentation = new SpaceJoin(metadata.Summary, xop.Documentation);
                //xop.CustomAttributes = pseudoCustomAttributes.Union(customAttributes);

                return xop;

            } else if (metadata is XsMember || metadata is XsContract) {

                XsdFormat xsd = null;

                if (metadata is XsMember) {

        #region metadata is ContractMember
                    var member = metadata as XsMember;
                    xsd = ToXsdRef(member.Contract, member.Name, member.IsAttribute, member.IsRequired);
                    var contract = member.Contract;

                    // defaultOnCreate
                    if (contract.CanBeEmpty)
                        pseudoCustomAttributes.Add(new XmlAttributeFormat(Xs.Nillable, true));

                    // default
                    if (member.ProvideDefault &&
                        !contract.IsEnumeration &&
                        member.Default as string != string.Empty) {

                        throw new NotImplementedException();
                        //pseudoCustomAttributes.Add(
                        //    new XmlAttributeFormat(Xs.Default,
                        //        Serializer.Serialize(member.Default).Value.ToLowerFirst()));
                    }

                    // group member names
                    if (member.Contract.IsGroup) {
                        pseudoCustomAttributes.Add(
                            new XmlAttributeFormat(XsType.XName, member.Name));
                    }

                    // defaultOnCreate
                    //if (member.DefaultOnCreate != null) {
                    //    pseudoCustomAttributes.Add(
                    //        new XmlAttribute(XMd.DefaultOnCreate, 
                    //            Serializer.Serialize(member.DefaultOnCreate).Value.ToLowerFirst()));
                    //}
                    #endregion

                } else if (metadata is XsContract) {
                    var contract = metadata as XsContract;
                    xsd = ToXsd(contract);
                    xsd.Comment = !Docs ? null : new object[] {
                        new Region("signatureTypeIn: ", new CommaJoin(Program.GetSignatureTypeIn(contract).Select(o => o.Name))),
                        new Region("subClasses: ", new CommaJoin(Program.GetSubClasses(contract).Select(o => o.Name))),
                        new Region("memberIn: ", new CommaJoin(Program.GetContractMemberIn(contract).Select(o => o.Name))),
                    };
                }

                xsd.Documentation = metadata.Summary;
                //xsd.CustomAttributes = pseudoCustomAttributes.Union(customAttributes);
                return xsd;

            }

            throw new ArgumentException();
        }
        internal static XsdFormat ToXsdRef(XsContract contract, string name, bool isAttribute, bool isRequired) {

            XsdFormat result = null;

            var qName = contract.FullName;

            if (contract.IsGroup) {
                result = new XsdGroupRef() {
                    CustomAttributes = new XAttribute(XsType.XName, name),
                    Ref = qName
                };

            } else if (isAttribute) {
                result = new XsdAttribute() {
                    Name = name,
                    Required = isRequired,
                    Type = qName,
                };

            } else if (contract.Constraints().Count() > 0) {
                object content =
                    from o in contract.Constraints()
                    select new XsdElement() {
                        Name = o.Name,
                        Type = o.FullName,
                        Optional = true
                    };

                if (contract.IsEnumeration) {
                    result = new XsdSequence() {
                        Repeating = contract.IsEnumeration,
                        Content = content
                    };

                } else if (contract.IsObject) {
                    result = new XsdChoice(content);

                } else {
                    throw new ArgumentException();
                }

                result = new XsdElement() {
                    Name = name,
                    Type = name != null ? null : qName,
                    Optional = !isRequired,
                    Content = new XsdComplexType() {
                        Elements = result
                    }
                };

            } else {
                result = new XsdElement() {
                    Name = name,
                    Optional = !isRequired,
                    Type = qName
                };
            }

            return result;
        }
        internal static XopFormat ToXsd(XsOperation operation) {
            var result = new XopOperation() {
                Name = operation.Name.ToLowerFirst(),
                IsStatic = operation.IsStatic,
                Return = operation.ReturnParameter.ToXsd(),
                Parameters = from o in operation.Parameters() select o.ToXsd()
            };

            return result;
        }
        internal static XsdFormat ToXsd(XsContract contract) {
            XsdFormat result = null;

            if (contract.IsGroup) {
                result = new XsdGroup() {
                    Name = contract.Name,

                    // members
                    Sequence =
                        from m in contract.DeclaredMembers()
                        group m by m.Order into g
                        select g.Count() == 1 ? g.Single().ToXsd() : new XsdChoice(from m in g select m.ToXsd())
                };

            } else if (contract.IsComplex) {
                var baseContract = contract.BaseContract;
                result = new XsdComplexType() {
                    Name = contract.Name,
                    IsAbstract = contract.IsAbstract,
                    Base = baseContract.IsObject ? null : baseContract.FullName,
                    IsRestriction = baseContract.IsDeriveByRestriction,

                    // operations
                    AppInfo = from m in contract.Operations() select m.ToXsd(),

                    // members (attributes)
                    Attributes =
                        from m in contract.DeclaredMembers()
                        where m.IsAttribute
                        select m.ToXsd(),

                    // members (elements)
                    Elements = new XsdSequence(
                        from m in contract.DeclaredMembers()
                        where !m.IsAttribute
                        group m by m.Order into g
                        select g.Count() == 1 ? g.Single().ToXsd() : new XsdChoice(from m in g select m.ToXsd())
                    )
                };

            } else {
                var baseContract = contract.BaseContract;

                var restriction = new XsdSimpleTypeRestriction() {
                    Base = baseContract.IsObject ? Xs.XString : baseContract.FullName,
                    Pattern = contract.Regex,
                    Enumeration = !contract.IsList ? null :
                        from o in contract.Enums().Take(Docs ? Program.BigEnumLimit : int.MaxValue)
                        select new XsdEnumeration() {
                            Value = o.Name.ToLowerFirst(),
                            Documentation = o.Summary
                        },
                };

                result = new XsdSimpleType() {
                    Documentation = contract.Summary,
                    Name = contract.Name,
                    List = !contract.IsFlags ? null : new XsdSimpleType() { Restriction = restriction },
                    Restriction = contract.IsFlags ? null : restriction
                };
            }

            return result;
        }
        internal static XsdFormat Generate() {

            var entity = XsLoader.GetContractOrNull("Entity");
            var schema = new XsdSchema() {
                Prefix = Xs.Prefix,
                ElementFormDefault = Xs.Qualified,
                TargetNamespace = XsInfoset.XNamespace,

                Content = new object[] {
                    new XmlAttributeFormat(XNamespace.Xmlns + XsType.Prefix, XsType.XNamespace),
                    new XmlAttributeFormat(XNamespace.Xmlns + XsInfoset.Prefix, XsInfoset.XNamespace),
                    new XmlAttributeFormat(XNamespace.Xmlns + XsType.Prefix, XsType.XNamespace),

        #region Global elements
                    new XmlTextFormat(Environment.NewLine),
                    new XmlCommentFormat("Global elements (enables xml intellisense)"),
                    from o in XsLoader.Contracts()
                    where o.IsComplex 
                    where !o.IsObject && 
                          !o.IsGroup && 
                          !o.IsEnumeration
                    select new XsdElement() {
                        Name = o.Name,
                        Type = o.FullName
                    },
                    #endregion

        #region Object, Enumeration, Xml, and BuiltIn Data Contract
                    Environment.NewLine,
                    new XmlCommentFormat("Enumeration Data Contract"),
                    new XsdComplexType() {
                        Name = XsLoader.EnumerationContract.Name,
                        Elements = new XsdSequence( 
                            new XsdAny() {
                                Namespace = Xs.AnyElementType,
                                MinOccurs = 0,
                                MaxOccurs = Xs.Unbounded
                            }
                        )
                    },

                    Environment.NewLine,
                    new XmlCommentFormat("Xml Data Contract"),
                    new XsdComplexType() {
                        Name = XsLoader.XmlContract.Name,
                        Elements = new XsdSequence(new XsdAny())
                    },

                    Environment.NewLine,
                    new XmlCommentFormat("BuiltIn Data Contracts"),
                    from o in XsLoader.Contracts()
                    where !o.IsObject && !o.IsPrimitive
                    select o.ToXsd(),
                    #endregion

        #region Regex and Simple Data Contracts
                    Environment.NewLine,
                    new XmlCommentFormat("Simple Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsSimple
                    where !o.IsPrimitive && !o.IsList
                    select o.ToXsd(),
                    #endregion

        #region Group, Abstract, Entity, and Complex Data Contracts
                    Environment.NewLine,
                    new XmlCommentFormat("Group Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsGroup
                    select o.ToXsd(),
                    #endregion

        #region Abstract Data Contracts
                    Environment.NewLine,
                    new XmlCommentFormat("Abstract Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsAbstract
                    orderby o.ToLinkList(x => x.BaseContract).Count()                    
                    select o.ToXsd(),
                    #endregion

        #region Entity Data Contracts
                    Environment.NewLine,
                    new XmlCommentFormat("Entity Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsDerivationOf(entity) && !o.IsAbstract && !o.IsGroup
                    select o.ToXsd(),
                    #endregion

        #region Complex Data Contracts
                    Environment.NewLine,
                    new XmlCommentFormat("Complex Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsComplex 
                    where !o.IsObject &&
                          !o.IsDerivationOf(entity) && o != entity &&
                          !o.IsAbstract &&                     
                          !o.IsGroup
                    select o.ToXsd(),
                    #endregion

        #region Flag and Enum Data Contracts
                    Environment.NewLine,
                    new XmlCommentFormat("Flag Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsList && o.IsFlags
                    select o.ToXsd(),

                    Environment.NewLine,
                    new XmlCommentFormat("Enum Data Contracts"),
                    from o in XsLoader.Contracts()
                    where o.IsList && !o.IsFlags
                    select o.ToXsd(),
                    #endregion
                }
            };

            return schema;
        }
        #endregion
#endif
    }

    // /queryable King\King.Linq\Queryable.Generated.cs
    [Command]
    internal static class QueryableGen {

        public static object EmitMethod(MethodInfo m) {
            var nl = Environment.NewLine;

            var code = new CSMethod() {
                Visibility = CSVisibility.Public,
                IsStatic = true,
                IsExtension = true,
                Name = m.Name,
                Returns = m.ReturnType,
                GenericArguments = m.GetGenericArguments(),
                Parameters = from o in m.GetParameters()
                             select new CSParameter(o.ParameterType, o.Name),
                Body = new TSingleLineJoin() {
                    new TObjects() {
                        @"var method = ((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(",
                        new TJoin(", ") { 
                            from g in m.GetGenericArguments() 
                            select new CSTypeOf(g) 
                        },
                        ");",
                    },
                    new TObjects() {
                        @"return Invoke<", m.ReturnType, 
                            !typeof(IQueryable).IsAssignableFrom(m.ReturnType) ? null : 
                                new object[] { ", ", 
                                    m.ReturnType.IsGenericType ? 
                                        m.ReturnType.GetGenericArguments()[0] : 
                                        typeof(object)
                                },

                        ">(method, ", 
                            new TJoin(", ") { 
                                from p in m.GetParameters() 
                                select p.Name 
                            },
                        ");",
                    }
                }
            };

            return code;
        }
        public static string Generate() {
            var code = new TDoubleLineJoin() {
                new CSUsingNamespace() {
                    "System",
                    "System.Reflection",
                    "System.Collections",
                    "System.Collections.Generic",
                    "System.Linq",
                    "System.Linq.Expressions",
                    "System.Data.Linq",
                    "System.Data.Linq.Mapping",
                    "King.Extensions"
                },

                new CSNamespace("King.Linq") {
                    new CSClass() {
                        Visibility = CSVisibility.Public,
                        IsPartial = true,
                        Name = "KingQueryable",
                        Members = new TSingleLineJoin() {
                            from o in typeof(Queryable).GetStaticPublic<MethodInfo>()
                            orderby typeof(IQueryable).IsAssignableFrom(o.ReturnType), o.Name
                            select EmitMethod(o),
                        }
                    }
                }
            };

            return code.Evaluate()
                .Replace("IQueryable", "IKingQueryable")
                .Replace("IOrderedQueryable", "IKingOrderedQueryable")
                .Replace("TSource", "T");
        }
    }

    // /microsoftTables KingDatabase\Microsoft\Linq.Generated.cs "Data Source=dev-db-01;Initial Catalog=master;User ID=srApp;Password=May15Live;"
    [Command]
    internal static class MicrosoftTables {

        #region Definitions
        public class GoogleResult {

            #region Private Data Members
            private Uri m_url;
            private string m_title;
            #endregion

            #region Constructor
            internal GoogleResult(Uri url, string title) {
                m_url = url;
                m_title = title;
            }
            #endregion

            #region Public Members
            public Uri Url { get { return m_url; } }
            public string Title { get { return m_title; } }
            #endregion

            #region Object Overrides
            public override string ToString() {
                return m_title;
            }
            #endregion
        }
        public class RestServices {

            #region Static Public Members
            public static IEnumerable<GoogleResult> GoogleSearch(string search) {
                for (var start = 0; start < 8; start += 8) {
                    var rest = new Uri("http://ajax.googleapis.com/" +
                        "ajax/services/search/" +
                        "web?v=1.0&q={0}&rsz=large&start={1}"
                        .Substitute(search, start));

                    var xml = RestServices.GetJsonAsXml(rest);

                    var result =
                        from o in xml.Descendants("object")
                        let fields =
                            from f in o.Elements("field")
                            select new {
                                Name = (string)f.Attribute("name"),
                                Value = (string)f.Attribute("value")
                            }
                        let url = fields.SingleOrDefault(f => f.Name == "unescapedUrl")
                        let title = fields.SingleOrDefault(f => f.Name == "titleNoFormatting")
                        where url != null && title != null
                        select new GoogleResult(new Uri(url.Value), title.Value);

                    foreach (var o in result)
                        yield return o;
                }
            }
            public static XElement JsonToXml(string json) {
                var list = new List<string>();
                int id = 0;
                var xml = json;

                xml = Regex.Replace(xml,
                    "\"(?<string>[^\"]*)\"",
                    delegate(Match match) {
                        var thisId = id++;
                        list.Add(match.Groups["string"].ToString());
                        return "\"" + thisId + "\"";
                    });

                xml = xml
                    .Replace("{", "<object>").Replace("}", "</object>")
                    .Replace("[", "<array>").Replace("]", "</array>");

                xml = Regex.Replace(xml,
                    @"{(?<name>\d*)}\s*:\s*<(?<type>object|array)>",
                    @"<${type} name='{${name}}'>");

                xml = Regex.Replace(xml,
                    @"\s*(?<name>[^>,:]*)\s*:\s*(?<value>[^<,]*)\s*(?=[<,])",
                    @"<field name='${name}' value='${value}'/>");

                xml = xml.Split(',').StringJoin("", o => o.StartsWith("<") ? o : "<element value='{0}'/>");

                xml = Regex.Replace(xml,
                    @"""(?<id>\d+)""",
                    delegate(Match match) { return list[int.Parse(match.Groups["id"].Value)]; });

                var result = XElement.Parse(xml);
                return result;
            }
            public static XElement GetJsonAsXml(Uri uri) {
                return JsonToXml(Get(uri));
            }
            public static XElement GetXml(Uri uri) {
                return XElement.Load(new XmlTextReader(Get(uri)));
            }
            public static string Get(Uri uri) {
                WebRequest webRequest = WebRequest.Create(uri);
                var result = new StreamReader(webRequest.GetResponse().GetResponseStream()).ReadToEnd();
                return result;
            }
            public static bool IsWord(string word) {
                // http://services.aonaware.com/DictService/DictService.asmx
                var rest = new Uri("http://services.aonaware.com/" +
                    "DictService/DictService.asmx/" +
                    "MatchInDict?dictId=gcide&word={0}&strategy=exact"
                    .Substitute(word));

                var xml = GetXml(rest);

                var result = xml.HasElements;
                return result;
            }
            #endregion
        }

        public enum Types {
        }
        public sealed class SystemViewCategoryAttribute : Attribute { }
        public sealed class SystemObjectTableAttribute : Attribute {
            private string[] m_types;
            public SystemObjectTableAttribute(params string[] types) {
                m_types = types;
            }
            public string[] Types { get { return m_types; } }
        }

        [SystemViewCategory]
        public class Reflection {

            public enum Objects {
                AllObjects,
                SystemObjects,
                Objects,

                [SystemObjectTable("V")]
                AllViews,
                [SystemObjectTable("V")]
                Views,
                [SystemObjectTable("V")]
                SystemViews,

                [SystemObjectTable("C")]
                CheckConstraints,

                [SystemObjectTable("D")]
                DefaultConstraints,

                [SystemObjectTable("X")]
                ExtendedProcedures,

                [SystemObjectTable("F")]
                ForeignKeys,

                [SystemObjectTable("PK", "UQ")]
                KeyConstraints,

                [SystemObjectTable("P", "X", "RF", "PC")]
                Procedures,

                [SystemObjectTable("SQ")]
                ServiceQueues,

                [SystemObjectTable("SN")]
                Synonyms,

                [SystemObjectTable("U")]
                Tables,

                [SystemObjectTable("IT")]
                InternalTables,
            }

            public enum Metadata {
                AllColumns,
                AllParameters,
                AllSqlModules,

                SystemColumns,
                SystemParameters,
                SystemSqlModules,

                IndexColumns,
                AllocationUnits,
                AssemblyModules,
                Columns,
                ComputedColumns,
                Events,
                EventNotifications,
                EventNotificationEventTypes,
                ForeignKeyColumns,
                IdentityColumns,
                Indexes,
                ModuleAssemblyUsages,
                NumberedProcedures,
                NumberedProcedureParameters,
                Parameters,
                Partitions,
                PlanGuides,
                ServerAssemblyModules,
                ServerEvents,
                ServerEventNotifications,
                ServerSqlModules,
                ServerTriggers,
                ServerTriggerEvents,
                SpatialIndexes,
                SpatialIndexTessellations,
                SqlDependencies,
                SqlExpressionDependencies,
                SqlModules,
                Stats,
                StatsColumns,
                TableTypes,
                TriggerEventTypes,
                TriggerEvents,
                Triggers,
                FunctionOrderColumns,
            }
        }

        [SystemViewCategory]
        public class CatalogViews {
            public enum ChangeTracking {
                ChangeTrackingDatabases,
                ChangeTrackingTables,
            }
            public enum ClrAssembly {
                Assemblies,
                AssemblyFiles,
                AssemblyReferences,
            }
            public enum DataCollector {
                SysCollectorCollectionItems,
                SysCollectorCollectionSets,
                SysCollectorCollectorTypes,
                SysCollectorConfigStore,
                SysCollectorExecutionLog,
                SysCollectorExecutionLogFull,
                SysCollectorExecutionStats,
            }
            public enum DataSpaces {
                DataSpaces,
                DestinationDataSpaces,
                FileGroups,
                PartitionSchemes,
            }
            public enum Mail {
                SysMailAllItems,
                SysMailEventLog,
                SysMailFailedItems,
                SysMailMailAttachments,
                SysMailSentItems,
                SysMailUnsentItems,
            }
            public enum MirroringWitness {
                DatabaseMirroringWitnesses,
            }
            public enum DatabasesAndCatalog {
                BackupDevices,
                Databases,
                DatabaseFiles,
                DatabaseMirroring,
                DatabaseRecoveryStatus,
                MasterFiles,
            }
            public enum Endpoints {
                DatabaseMirroringEndpoints,
                EndPoints,
                EndPointWebMethods,
                HttpEndPoints,
                ServiceBrokerEndPoints,
                SoapEndPoints,
                TcpEndPoints,
                ViaEndPoints,
            }
            public enum ExtendedEvents {
                ServerEventSessions,
                ServerEventSessionActions,
                ServerEventSessionEvents,
                ServerEventSessionFields,
                ServerEventSessionTargets
            }
            public enum ExtendedProperties {
                ExtendedProperties,
            }
            public enum FullTextSearch {
                FullTextCatalogs,
                FullTextDocumentTypes,
                FullTextIndexCatalogUsages,
                FullTextIndexColumns,
                FullTextIndexFragments,
                FullTextIndexes,
                FullTextLanguages,
                FullTextStopLists,
                FullTextStopWords,
                FullTextSystemStopWords,
            }
            public enum LinkedServers {
                LinkedLogins,
                RemoteLogins,
                Servers,
            }
            public enum CatalogErrorMessages {
                Messages,
            }
            public enum PartitionFunction {
                PartitionFunctions,
                PartitionParameters,
                PartitionRangeValues,
            }
            public enum PolicyBasedManagement {
                SysPolicyConditions,
                SysPolicyPolicies,
                SysPolicyPolicyExecutionHistory,
                SysPolicyPolicyExecutionHistoryDetails,
                SysPolicyPolicyCategories,
                SysPolicyPolicyCategorySubscriptions,
                SysPolicySystemHealthState,
            }
            public enum ResourceGovernor {
                ResourceGovernorConfiguration,
                ResourceGovernorResourcePools,
                ResourceGovernorWorkLoadGroups,
            }
            public enum ScalarTypes {
                AssemblyTypes,
                Types,
                TypeAssemblyUsages,
                ColumnTypeUsages,
                ParameterTypeUsages,
            }
            public enum Schemas {
                Schemas,
            }
            public enum Security {
                AsymmetricKeys,
                Certificates,
                Credentials,
                CryptProperties,
                CryptographicProviders,
                DatabaseAuditSpecifications,
                DatabaseAuditSpecificationDetails,
                DatabasePermissions,
                DatabasePrincipals,
                DatabaseRoleMembers,
                KeyEncryptions,
                MasterKeyPasswords,
                OpenKeys,
                SecurableClasses,
                ServerAudits,
                ServerAuditSpecifications,
                ServerAuditSpecificationDetails,
                ServerFileAudits,
                ServerPermissions,
                ServerPrincipals,
                ServerRoleMembers,
                SqlLogins,
                SymmetricKeys,
                SystemComponentsSurfaceAreaConfiguration,
            }
            public enum ServiceBroker {
                ConversationEndPoints,
                ConversationGroups,
                MessageTypeXmlSchemaCollectionUsages,
                RemoteServiceBindings,
                Routes,
                ServiceContracts,
                ServiceContractMessageUsages,
                ServiceContractUsages,
                ServiceMessageTypes,
                ServiceQueueUsages,
                Services,
                TransmissionQueue,
                ConversionPriorities
            }
            public enum ServerWideConfiguration {
                Configurations,
                Traces,
                TraceCategories,
                TraceColumns,
                TraceEvents,
                TraceEventBindings,
                TraceSubClassValues
            }
            public enum XmlSchemas {
                ColumnXmlSchemaCollectionUsages,
                ParameterXmlSchemaCollectionUsages,
                XmlSchemaAttributes,
                XmlSchemaComponentPlacements,
                XmlSchemaComponents,
                XmlSchemaElements,
                XmlSchemaFacets,
                XmlIndexes,
                XmlSchemaModelGroups,
                XmlSchemaCollections,
                XmlSchemaNamespaces,
                XmlSchemaTypes,
                XmlSchemaWildcardNamespaces,
                XmlSchemaWildCards,
            }
        }
        [SystemViewCategory]
        public class DynamicManagementViews {
            public enum ChangeDataCapture {
                DmCdcLogScanSessions,
                DmCdcErrors,
            }
            public enum ChangeTracking {
                DmTranCommitTable,
            }
            public enum Clr {
                DmClrAppDomains,
                DmClrLoadedAssemblies,
                DmClrProperties,
                DmClrTasks,
            }
            public enum Mirroring {
                DmDbMirroringConnections,
                DmDbMirroringAutoPageRepair,
            }
            public enum Database {
                DmDbFileSpaceUsage,
                DmDbPartitionStats,
                DmDbPersistedSkuFeatures,
                DmDbSessionSpaceUsage,
                DmDbTaskSpaceUsage
            }
            public enum Execution {
                DmExecBackgroundJobQueue,
                DmExecBackGroundJobQueueStats,
                DmExecCachedPlans,
                DmExecCachedPlanDependentObjects,
                DmExecConnections,
                DmExecCursors,
                DmExecPlanAttributes,
                DmExecQueryMemoryGrants,
                DmExecQueryOptimizerInfo, QueryPlan,
                DmExecProcedureStats,
                DmExecQueryResourceSemaphores,
                DmExecQueryStats,
                DmExecRequests,
                DmExecSessions,
                DmExecSqlText,
                DmExecTriggerStats,
                DmExecTextQueryPlan,
                DmExecXmlHandles,

                DmExecQueryTransformationStats
            }
            public enum ExtendedEvent {
                DmOsDispatcherPools,
                DmXeMapValues,
                DmXeObjectColumns,
                DmXeObjects,
                DmXePackages,
                DmXeSessionEventActions,
                DmXeSessionEvents,
                DmXeSessionObjectColumns,
                DmXeSessionTargets,
                DmXeSessions,
            }
            public enum FullTextSearch {
                DmFtsActiveCatalogs,
                DmFtsFdHosts,
                DmFtsIndexKeywords,
                DmFtsIndexKeyWordsByDocument,
                DmFtsIndexPopulation,
                DmFtsMemoryBuffers,
                DmFtsMemoryPools,
                DmFtsOutstandingBatches,
                DmFtsParser,
                DmFtsPopulationRanges,
            }
            public enum Index {
                DmDbIndexOperationalStats,
                DmDbIndexPhysicalStats,
                DmDbIndexUsageStats,
                DmDbMissingIndexColumns,
                DmDbMissingIndexDetails,
                DmDbMissingIndexGroups,
                DmDbMissingIndexGroupStats,
            }
            public enum IO {
                DmIoBackupTapes,
                DmIoClusterSharedDrives,
                DmIoPendingIoRequests,
                DmIoVirtualFileStats,
            }
            public enum ObjectRelated {
                DmSqlReferencedEntities,
                DmSqlReferencingEntities,
            }
            public enum QueryNotifications {
                DmQnSubscriptions,
            }
            public enum Replication {
                DmReplArticles,
                DmReplSchemas,
                DmReplTranHash,
                DmReplTranInfo,
            }
            public enum ResourceCovernor {
                DmResourceGovernorConfiguration,
                DmResourceGovernorResourcePools,
                DmResourceGovernorWorkloadGroups,
            }
            public enum ServiceBroker {
                DmBrokerActivatedTasks,
                DmBrokerConnections,
                DmBrokerForwardedMessages,
                DmBrokerQueueMonitors,
            }
            public enum SqlServerOperatingSystem {
                DmOsBufferDescriptors,
                DmOsChildInstances,
                DmOsClusterNodes,
                DmOsHosts,
                DmOsLatchStats,
                DmOsLoadedModules,
                DmOsMemoryCacheClockHands,
                DmOsMemoryCacheCounters,
                DmOsMemoryCacheEntries,
                DmOsMemoryCacheHashTables,
                DmOsMemoryClerks,
                DmOsMemoryObjects,
                DmOsMemoryPools,
                DmOsPerformanceCounters,
                DmOsSchedulers,
                DmOsStacks,
                DmOsSysInfo,
                DmOsTasks,
                DmOsThreads,
                DmOsVirtualAddressDump,
                DmOsWaitingTasks,
                DmOsWaitStats,
                DmOsWorkers,
                DmOsMemoryBrokers,
                DmOsMemoryNodes,
                DmOsNodes,
                DmOsProcessMemory,
                DmOsSysMemory,

                DmOsFunctionSymbolicName,
                DmOsMemoryAllocations,
                DmOsWorkerLocalStorage,
                DmOsRingBuffers,
                DmOsSublatches,
            }
            public enum Transaction {
                DmTranActiveSnapshotDatabaseTransactions,
                DmTranActiveTransactions,
                DmTranCurrentSnapshot,
                DmTranCurrentTransaction,
                DmTranDatabaseTransactions,
                DmTranLocks,
                DmTranSessionTransactions,
                DmTranTopVersionGenerators,
                DmTranTransactionsSnapshot,
                DmTranVersionStore,
            }
            public enum Security {
                DmAuditActions,
                DmCryptographicProviderAlgorithms,
                DmCryptographicProvicerKeys,
                DmCryptographicProviderProperties,
                DmCryptographicProviderSessions,
                DmDatabaseEncryptionKeys,
                DmServerAuditStatus
            }
        }

        [SystemViewCategory]
        public enum CompatibilityViews {
            SysAltFiles,
            SysCacheObjects,
            SysCharSets,
            SysColumns,
            SysComments,
            SysConfigures,
            SysConstraints,
            SysCurConfigs,
            SysDatabases,
            SysDepends,
            SysDevices,
            SysFileGroups,
            SysFiles,
            SysForeignKeys,
            SysFullTextCatalogs,
            SysIndexes,
            SysIndexKeys,
            SysLanguages,
            SysLockInfo,
            SysLogins,
            SysMembers,
            SysMessages,
            SysObjects,
            SysPerfInfo,
            SysPermissions,
            SysProcesses,
            SysProtects,
            SysReferences,
            SysRemoteLogins,
            SysServers,
            SysTypes,
            SysUsers,
        }
        [SystemViewCategory]
        public enum SystemBaseTables {
            SysSchObjs,
            SysBinObjs,
            SysClsObjs,
            SysNsObjs,
            SysColPars,
            SysTypedSubObjs,
            SysIndxStats,
            SysIsCols,
            SysScalarTypes,
            SysDbReg,
            SysXSrvs,
            SysRmtLgns,
            SysLnkLgns,
            SysDbFiles,
            SysUserMsg,
            SysPrivs,
            SysOwners,
            SysObjKeyCrypts,
            SysCerts,
            SysAsymKeys,
            FtInds,
            SysXProps,
            SysAllocUnits,
            SysRowSets,
            SysRowSetColumns,
            SysHoBts,
            SysHoBtColumns,
            SysSeRefs,
            SysRowSetRefs,
            SysLogShippers,
            SysRemSvcBinds,
            SysConvGroup,
            SysXMitQueue,
            SysDesEnd,
            SysDerCv,
            SysEndPts,
            SysWEbMethods,
            SysQNames,
            SysXmlComponent,
            SysXmlFacet,
            SysXmlPlacement,
            SysSingleObjRefs,
            SysMultiObjRefs,
            SysObjValues,
            SysGuidRefs
        }
        [SystemViewCategory]
        public enum Deprecated {
            DatabasePrincipalAliases
        }
        [SystemViewCategory]
        public enum Internal {
            SystemInternalsPartitions,
            SystemInternalsPartitionColumns,
            SystemInternalsAllocationUnits,
        }
        [SystemViewCategory]
        public enum Misc {
            LoginToken,
            UserToken
        }
        [SystemViewCategory]
        public enum Undocumented {
            SysCursorColumns,
            SysCursorRefs,
            SysCursors,
            SysCursorTables,
            SysFiles1,
            SysFullTextNotify,
            SysLocks,
            SysProperties,
            SysXLogins,

            SysBinSubObjs,
            SysFtinds,
            SysIdxStats,
            SysOleDbUsers,
            SysOpenTapes,
            SysRts,
            SysSegments,
            SysSqlGuides,

            SysChildInsts,
            SysUserMsgs,
            SysXLgns,
        }

        public class ViewInfo {

            #region Private Data Members
            private string m_category;
            private string m_subCategory;
            private string m_tableName;
            #endregion

            #region Constructor
            public ViewInfo(string tableName, string category, string subCategory) {
                m_tableName = tableName;
                m_category = category;
                m_subCategory = category == subCategory ? null : subCategory;
            }
            #endregion

            #region Public Members
            public string TableName { get { return m_tableName; } }
            public string SubCategory { get { return m_subCategory; } }
            public string Category { get { return m_category; } }
            #endregion

            #region Object Overrides
            public override string ToString() {
                return "{0} ({1}{2})".Substitute(TableName, Category, SubCategory == null ? null : ":" + SubCategory);
            }
            #endregion
        }
        #endregion

        #region Static Private Data Members
        private static Dictionary<string, ViewInfo> s_viewInfo;
        private static HashSet<SqlTable> s_objectTables;
        private static HashSet<SqlTable> s_objectBaseTables;
        private static HashSet<string> s_objectTableColumnNames;
        #endregion

        #region Static Constructor
        static MicrosoftTables() {
            try {

                var viewInfo =
                    from category in Assembly.GetExecutingAssembly().GetTypes()
                    where category.IsDefined<SystemViewCategoryAttribute>()
                    from subCategory in category.IsClass ? category.Get<Type>() : new[] { category }
                    from tableName in subCategory.GetStatic<FieldInfo>()
                    select new ViewInfo(tableName.Name, category.Name, subCategory.Name);

                s_viewInfo = viewInfo.ToDictionary(o => o.TableName.ToLower());

            } catch (Exception e) {
            }
        }
        #endregion

        #region Private Extensions
        private static string GetCachedName(this SqlTable table) {
            return GetNormalizedName(table.Name).ToLower();
        }
        private static string GetClrName(this SqlColumn column) {
            return GetNormalizedName(column.Name);
        }

        private static ViewInfo GetViewInfo(this SqlTable table) {
            return s_viewInfo[table.GetCachedName()];
        }
        private static string GetClrName(this SqlTable table) {
            return table.GetViewInfo().TableName;
        }
        private static string GetCategory(this SqlTable table) {
            return table.GetViewInfo().Category;
        }
        private static string GetSubCategory(this SqlTable table) {
            return table.GetViewInfo().SubCategory;
        }
        private static bool GetIsObjectTable(this SqlTable table) {
            return s_objectTables.Contains(table);
        }
        private static bool GetIsObjectBaseTable(this SqlTable table) {
            return s_objectBaseTables.Contains(table);
        }
        private static bool GetIsObjectTableColumn(this SqlColumn column) {
            return column.Table.GetIsObjectTable() && s_objectTableColumnNames.Contains(column.Name);
        }
        private static bool GetIsPrimaryKey(this SqlColumn column) {
            return column.Table.GetIsObjectTable() && column.Name == "object_id";
        }
        private static bool GetIsNullable(this SqlColumn column) {
            if (column.GetIsObjectTableColumn()) {
                if (new[] { "is_ms_shipped", "is_published", "is_schema_published" }.Contains(column.Name))
                    return true;
            }

            return column.SqlType.IsNillable && column.ClrType.IsValueType;
        }
        #endregion

        #region Static Private Members
        private static string GetNormalizedName(string name) {
            var result =
               (from o in name.Split('_')
                select o.ToUpperFirst())
                .StringJoin();
            return result;
        }
        private static Dictionary<SqlTable, Uri> GetDocUrls(IEnumerable<SqlTable> tables) {

            var result = new Dictionary<SqlTable, Uri>();

            foreach (var o in tables) {
                var title = o.Schema + "." + o.Name + " (Transact-SQL)";
                var search = RestServices.GoogleSearch(title);
                var page = search.FirstOrDefault(x => x.Title == title);
                if (page == null) {
                    Console.WriteLine(o.Name);
                } else {
                    result[o] = page.Url;
                    Console.WriteLine(o.Name + " " + page.Url);
                }
            }

            return result;
        }

        private static object Generate(SqlColumn column) {
            var columnType = column.SqlType;

            var code = new CSProperty() {
                Attributes = new CSAttributeGroup() {
                    new CSAttribute(typeof(ColumnAttribute)) {
                        new CSNamedArgument("Name", new CSString(column.Name)),
                        new CSNamedArgumentIf(column.GetIsPrimaryKey(), "IsPrimaryKey", true),
                        new CSNamedArgumentIf(!columnType.IsNillable, "CanBeNull", columnType.IsNillable),
                    },
                    new CSAttribute(typeof(SqlTypeAttribute)) {
                        column.SqlType.SystemType,
                        new CSNamedArgumentIf(columnType.HasLength, "Length", columnType.MaxLength),
                        new CSNamedArgumentIf(columnType.HasPrecision, "Precision", columnType.Precision),
                        new CSNamedArgumentIf(columnType.HasScale, "Scale", columnType.Scale),
                    }
                },
                Visibility = CSVisibility.Public,
                Type = new CSTypeBuilder(column.ClrType) {
                    IsNullable = column.GetIsNullable()
                },
                IsSealed = column.GetIsObjectTableColumn(),
                Name = column.GetClrName(),
            };

            return code;
        }
        private static object Generate(SqlTable table) {
            var code = new CSClass() {
                Attributes = new CSAttribute(typeof(TableAttribute)) {
                    new CSNamedArgument("Name", new CSString(table.Schema.Name + "." + table.Name))
                },
                Visibility = CSVisibility.Public,
                IsPartial = true,
                IsSealed = true,
                BaseType = table.GetIsObjectTable() ? "ObjectsBase" : null,
                Name = table.GetClrName(),

                Members = new TDoubleLine() {
                    new CSRegion("Associations") {
                        !table.GetIsObjectBaseTable() ? null : 
                        from o in s_objectTables.Except(s_objectBaseTables)
                        select new object[] {
                            new CSField() {
                                Visibility = CSVisibility.Private,
                                Name = "m_" + o.GetClrName().ToLowerFirst(),
                                Type = "EntityRef<" + o.GetClrName() + ">",
                            },
                            new CSProperty() {
                                Attributes = new CSAttribute(typeof(AssociationAttribute)) {
                                    new CSNamedArgument("ThisKey", new CSString("ObjectId")),
                                    new CSNamedArgument("IsForeignKey", true),
                                    new CSNamedArgument("Storage", new CSString("m_" + o.GetClrName().ToLowerFirst())),
                                },
                                Visibility = CSVisibility.Public,
                                Name = "As" + o.GetClrName(),
                                Type = o.GetClrName(),
                                GetterBody = "return m_" + o.GetClrName().ToLowerFirst() + ".Entity;",
                                SetterBody = "throw new NotImplementedException();",
                            }
                        }
                    },

                    new CSRegion("Public Members") {
                        from o in table.GetColumns()
                        orderby !o.GetIsPrimaryKey(), !o.GetIsObjectTableColumn(), o.Name
                        select Generate(o)
                    }
                }
            };

            return code;
        }
        private static object GenerateObjectBase(SqlTable table) {
            var code = new CSClass() {
                Visibility = CSVisibility.Public,
                IsPartial = true,
                IsAbstract = true,
                Name = "ObjectsBase",

                Members = new TDoubleLine() {
                    new CSRegion("Public Members") {
                        from o in table.GetColumns()
                        orderby o.Name
                        select new CSProperty() {                           
                            Visibility = CSVisibility.Public,
                            Type = new CSTypeBuilder(o.ClrType) {
                                IsNullable = o.GetIsNullable()
                            },
                            IsAbstract = true,                            
                            Name = o.GetClrName(),
                        }
                    }
                }
            };

            return code;
        }
        #endregion

        #region Static Internal Members
        internal static void Generate(string path, string connectionString) {
            var database = SqlDatabase.Connect(connectionString);

            var unCategorized = database.SystemSchema.GetTables()
                .Where(o => !s_viewInfo.ContainsKey(o.GetCachedName()))
                .Select(o => o.Name)
                .ToArray();
            foreach (var o in unCategorized)
                Console.WriteLine(o);

            var objectTable = database.SystemSchema.GetTable("objects");
            var allObjectTable = database.SystemSchema.GetTable("all_objects");
            var systemObjectsTable = database.SystemSchema.GetTable("SystemObjects");
            s_objectBaseTables = new[] { objectTable, allObjectTable, systemObjectsTable }.ToHashSet();

            s_objectTableColumnNames = objectTable.GetColumns().Select(o => o.Name).ToHashSet();
            s_objectTables =
               (from o in database.SystemSchema.GetTables()
                let columnNames = o.GetColumns().Select(x => x.Name).ToHashSet()
                where s_objectTableColumnNames.All(x => columnNames.Contains(x))
                orderby o.Name
                select o).ToHashSet();

            var code =
                new TDoubleLineJoin() {
                    new CSUsingNamespace() {
                        "System",
                        "System.Collections.Generic",
                        "System.Linq",
                        "System.Data.Linq",
                        "System.Data.Linq.Mapping"
                    },

                    new CSNamespace("King.Database.Microsoft") {
                        new TDoubleLine() {
                            GenerateObjectBase(objectTable),

                            from o in database.SystemSchema.GetTables()
                            group o by o.GetCategory() into o
                            select new CSRegion(o.Key) {
                                o.First().GetSubCategory() == null ? 

                                    // no subCategories
                                    from x in o
                                    select (object)Generate(x) :

                                    (object)new TDoubleLineJoin() {
                                        // subCategories
                                        from x in o
                                        group x by x.GetSubCategory() into x
                                        select new CSRegion(x.Key) {
                                            from y in x
                                            select Generate(y)
                                        }
                                    }
                            }
                        }
                    }
                };

            using (var file = new StreamWriter(path, false))
                file.WriteLine(code.Evaluate());
        }
        #endregion
    }
}


